github.com/mithrandie/csvq@v1.18.1/lib/query/query.go (about) 1 package query 2 3 import ( 4 "context" 5 "strings" 6 "sync/atomic" 7 8 "github.com/mithrandie/csvq/lib/option" 9 "github.com/mithrandie/csvq/lib/parser" 10 "github.com/mithrandie/csvq/lib/value" 11 ) 12 13 func FetchCursor(ctx context.Context, scope *ReferenceScope, name parser.Identifier, fetchPosition parser.FetchPosition, vars []parser.Variable) (bool, error) { 14 position := parser.NEXT 15 number := -1 16 if !fetchPosition.Position.IsEmpty() { 17 position = fetchPosition.Position.Token 18 if fetchPosition.Number != nil { 19 p, err := Evaluate(ctx, scope, fetchPosition.Number) 20 if err != nil { 21 return false, err 22 } 23 i := value.ToInteger(p) 24 if value.IsNull(i) { 25 return false, NewInvalidFetchPositionError(fetchPosition) 26 } 27 number = int(i.(*value.Integer).Raw()) 28 value.Discard(i) 29 } 30 } 31 32 primaries, err := scope.FetchCursor(name, position, number) 33 if err != nil { 34 return false, err 35 } 36 if primaries == nil { 37 return false, nil 38 } 39 if len(vars) != len(primaries) { 40 return false, NewCursorFetchLengthError(name, len(primaries)) 41 } 42 43 for i, v := range vars { 44 _, err := scope.SubstituteVariableDirectly(v, primaries[i]) 45 if err != nil { 46 return false, err 47 } 48 } 49 return true, nil 50 } 51 52 func DeclareView(ctx context.Context, scope *ReferenceScope, expr parser.ViewDeclaration) error { 53 if scope.TemporaryTableExists(expr.View.Literal) { 54 return NewTemporaryTableRedeclaredError(expr.View) 55 } 56 57 var view *View 58 var err error 59 60 if expr.Query != nil { 61 view, err = Select(ctx, scope, expr.Query.(parser.SelectQuery)) 62 if err != nil { 63 return err 64 } 65 66 if err := view.Header.Update(expr.View.Literal, expr.Fields); err != nil { 67 if _, ok := err.(*FieldLengthNotMatchError); ok { 68 return NewTemporaryTableFieldLengthError(expr.Query.(parser.SelectQuery), expr.View, len(expr.Fields)) 69 } 70 return err 71 } 72 } else { 73 fields := make([]string, len(expr.Fields)) 74 fieldsMap := make(map[string]bool, len(expr.Fields)) 75 for i := range expr.Fields { 76 lit := expr.Fields[i].(parser.Identifier).Literal 77 ulit := strings.ToUpper(lit) 78 if _, ok := fieldsMap[ulit]; ok { 79 return NewDuplicateFieldNameError(expr.Fields[i].(parser.Identifier)) 80 } 81 fields[i] = lit 82 fieldsMap[ulit] = true 83 } 84 header := NewHeader(expr.View.Literal, fields) 85 view = NewView() 86 view.Header = header 87 view.RecordSet = RecordSet{} 88 } 89 90 view.FileInfo = NewTemporaryTableFileInfo(expr.View.Literal) 91 view.CreateRestorePoint() 92 93 scope.SetTemporaryTable(view) 94 95 return err 96 } 97 98 func Select(ctx context.Context, scope *ReferenceScope, query parser.SelectQuery) (*View, error) { 99 var intoVars []parser.Variable = nil 100 if selectEntity, ok := query.SelectEntity.(parser.SelectEntity); ok && selectEntity.IntoClause != nil { 101 intoClause := selectEntity.IntoClause.(parser.IntoClause) 102 if len(selectEntity.SelectClause.(parser.SelectClause).Fields) != len(intoClause.Variables) { 103 return nil, NewSelectIntoQueryFieldLengthNotMatchError(query, len(intoClause.Variables)) 104 } 105 for _, v := range intoClause.Variables { 106 if _, err := scope.GetVariable(v); err != nil { 107 return nil, err 108 } 109 } 110 intoVars = intoClause.Variables 111 } 112 113 queryScope := scope.CreateNode() 114 115 if query.WithClause != nil { 116 if err := queryScope.LoadInlineTable(ctx, query.WithClause.(parser.WithClause)); err != nil { 117 queryScope.CloseCurrentNode() 118 return nil, err 119 } 120 } 121 122 view, err := selectEntity( 123 ctx, 124 queryScope, 125 query.SelectEntity, 126 query.IsForUpdate(), 127 ) 128 if err != nil { 129 queryScope.CloseCurrentNode() 130 return nil, err 131 } 132 133 if query.OrderByClause != nil { 134 if err := view.OrderBy(ctx, queryScope, query.OrderByClause.(parser.OrderByClause)); err != nil { 135 queryScope.CloseCurrentNode() 136 return nil, err 137 } 138 } 139 140 if query.LimitClause != nil { 141 limitClause := query.LimitClause.(parser.LimitClause) 142 if limitClause.OffsetClause != nil { 143 if err := view.Offset(ctx, queryScope, limitClause.OffsetClause.(parser.OffsetClause)); err != nil { 144 queryScope.CloseCurrentNode() 145 return nil, err 146 } 147 } 148 149 if !limitClause.Type.IsEmpty() { 150 if err := view.Limit(ctx, queryScope, limitClause); err != nil { 151 queryScope.CloseCurrentNode() 152 return nil, err 153 } 154 } 155 } 156 157 err = view.Fix(ctx, queryScope.Tx.Flags) 158 queryScope.CloseCurrentNode() 159 160 if err == nil && intoVars != nil { 161 if view.FieldLen() != len(intoVars) { 162 return nil, NewSelectIntoQueryFieldLengthNotMatchError(query, len(intoVars)) 163 } 164 switch view.RecordLen() { 165 case 0: 166 for _, v := range intoVars { 167 if _, err := scope.SubstituteVariableDirectly(v, value.NewNull()); err != nil { 168 return view, err 169 } 170 } 171 case 1: 172 for i, v := range intoVars { 173 if _, err := scope.SubstituteVariableDirectly(v, view.RecordSet[0][i][0]); err != nil { 174 return view, err 175 } 176 } 177 default: 178 return view, NewSelectIntoQueryTooManyRecordsError(query) 179 } 180 } 181 182 return view, err 183 } 184 185 func selectEntity(ctx context.Context, scope *ReferenceScope, expr parser.QueryExpression, forUpdate bool) (*View, error) { 186 entity, ok := expr.(parser.SelectEntity) 187 if !ok { 188 return selectSet(ctx, scope, expr.(parser.SelectSet), forUpdate) 189 } 190 191 if entity.FromClause == nil { 192 entity.FromClause = parser.FromClause{} 193 } 194 view, err := LoadView(ctx, scope, entity.FromClause.(parser.FromClause).Tables, forUpdate, false) 195 if err != nil { 196 return nil, err 197 } 198 199 if entity.WhereClause != nil { 200 if err := view.Where(ctx, scope, entity.WhereClause.(parser.WhereClause)); err != nil { 201 return nil, err 202 } 203 } 204 205 if entity.GroupByClause != nil { 206 if err := view.GroupBy(ctx, scope, entity.GroupByClause.(parser.GroupByClause)); err != nil { 207 return nil, err 208 } 209 } 210 211 if entity.HavingClause != nil { 212 if err := view.Having(ctx, scope, entity.HavingClause.(parser.HavingClause)); err != nil { 213 return nil, err 214 } 215 } 216 217 if err := view.Select(ctx, scope, entity.SelectClause.(parser.SelectClause)); err != nil { 218 return nil, err 219 } 220 221 return view, nil 222 } 223 224 func selectSetEntity(ctx context.Context, scope *ReferenceScope, expr parser.QueryExpression, forUpdate bool) (*View, error) { 225 if subquery, ok := expr.(parser.Subquery); ok { 226 return Select(ctx, scope, subquery.Query) 227 } 228 229 view, err := selectEntity(ctx, scope, expr, forUpdate) 230 if err != nil { 231 return nil, err 232 } 233 err = view.Fix(ctx, scope.Tx.Flags) 234 return view, err 235 } 236 237 func selectSet(ctx context.Context, scope *ReferenceScope, set parser.SelectSet, forUpdate bool) (*View, error) { 238 lview, err := selectSetEntity(ctx, scope, set.LHS, forUpdate) 239 if err != nil { 240 return nil, err 241 } 242 243 if scope.RecursiveTable != nil { 244 scope.RecursiveTmpView = nil 245 err := selectSetForRecursion(ctx, scope, lview, set, forUpdate) 246 if err != nil { 247 return nil, err 248 } 249 } else { 250 queryScope := scope.CreateNode() 251 rview, err := selectSetEntity(ctx, queryScope, set.RHS, forUpdate) 252 queryScope.CloseCurrentNode() 253 queryScope = nil 254 if err != nil { 255 return nil, err 256 } 257 258 if lview.FieldLen() != rview.FieldLen() { 259 return nil, NewCombinedSetFieldLengthError(set.RHS, lview.FieldLen()) 260 } 261 262 switch set.Operator.Token { 263 case parser.UNION: 264 if err = lview.Union(ctx, scope.Tx.Flags, rview, !set.All.IsEmpty()); err != nil { 265 return nil, err 266 } 267 case parser.EXCEPT: 268 if err = lview.Except(ctx, scope.Tx.Flags, rview, !set.All.IsEmpty()); err != nil { 269 return nil, err 270 } 271 case parser.INTERSECT: 272 if err = lview.Intersect(ctx, scope.Tx.Flags, rview, !set.All.IsEmpty()); err != nil { 273 return nil, err 274 } 275 } 276 } 277 278 err = lview.SelectAllColumns(ctx, scope) 279 return lview, err 280 } 281 282 func selectSetForRecursion(ctx context.Context, scope *ReferenceScope, view *View, set parser.SelectSet, forUpdate bool) error { 283 if ctx.Err() != nil { 284 return ConvertContextError(ctx.Err()) 285 } 286 287 if -1 < scope.Tx.Flags.LimitRecursion { 288 if scope.RecursiveCount == nil { 289 scope.RecursiveCount = new(int64) 290 } 291 atomic.AddInt64(scope.RecursiveCount, 1) 292 if scope.Tx.Flags.LimitRecursion < *scope.RecursiveCount { 293 return NewRecursionExceededLimitError(set.RHS, scope.Tx.Flags.LimitRecursion) 294 } 295 } 296 297 tmpViewName := strings.ToUpper(scope.RecursiveTable.Name.Literal) 298 299 if scope.RecursiveTmpView == nil { 300 err := view.Header.Update(tmpViewName, scope.RecursiveTable.Fields) 301 if err != nil { 302 return err 303 } 304 scope.RecursiveTmpView = view 305 } 306 307 queryScope := scope.CreateNode() 308 rview, err := selectSetEntity(ctx, queryScope, set.RHS, forUpdate) 309 queryScope.CloseCurrentNode() 310 queryScope = nil 311 if err != nil { 312 return err 313 } 314 if view.FieldLen() != rview.FieldLen() { 315 return NewCombinedSetFieldLengthError(set.RHS, view.FieldLen()) 316 } 317 318 if rview.RecordLen() < 1 { 319 return nil 320 } 321 322 switch set.Operator.Token { 323 case parser.UNION: 324 if err = view.Union(ctx, scope.Tx.Flags, rview, !set.All.IsEmpty()); err != nil { 325 return err 326 } 327 case parser.EXCEPT: 328 if err = view.Except(ctx, scope.Tx.Flags, rview, !set.All.IsEmpty()); err != nil { 329 return err 330 } 331 case parser.INTERSECT: 332 if err = view.Intersect(ctx, scope.Tx.Flags, rview, !set.All.IsEmpty()); err != nil { 333 return err 334 } 335 } 336 337 if err = rview.Header.Update(tmpViewName, scope.RecursiveTable.Fields); err != nil { 338 return err 339 } 340 scope.RecursiveTmpView = rview 341 342 return selectSetForRecursion(ctx, scope, view, set, forUpdate) 343 } 344 345 func Insert(ctx context.Context, scope *ReferenceScope, query parser.InsertQuery) (*FileInfo, int, error) { 346 queryScope := scope.CreateNode() 347 defer queryScope.CloseCurrentNode() 348 349 var insertRecords int 350 351 if query.WithClause != nil { 352 if err := queryScope.LoadInlineTable(ctx, query.WithClause.(parser.WithClause)); err != nil { 353 return nil, insertRecords, err 354 } 355 } 356 357 tables := []parser.QueryExpression{ 358 query.Table, 359 } 360 361 queryScope.Tx.operationMutex.Lock() 362 defer queryScope.Tx.operationMutex.Unlock() 363 364 view, err := LoadView(ctx, queryScope, tables, true, false) 365 if err != nil { 366 return nil, insertRecords, err 367 } 368 if !view.IsUpdatable() { 369 return nil, insertRecords, NewInlineTableCannotBeUpdatedError(query.Table.Object) 370 } 371 372 fields := query.Fields 373 if fields == nil { 374 fields = view.Header.TableColumns() 375 } 376 377 if query.ValuesList != nil { 378 if insertRecords, err = view.InsertValues(ctx, queryScope, fields, query.ValuesList); err != nil { 379 return nil, insertRecords, err 380 } 381 } else { 382 if insertRecords, err = view.InsertFromQuery(ctx, queryScope, fields, query.Query.(parser.SelectQuery)); err != nil { 383 return nil, insertRecords, err 384 } 385 } 386 387 if err = view.RestoreHeaderReferences(); err != nil { 388 return nil, insertRecords, err 389 } 390 391 if view.FileInfo.IsInMemoryTable() { 392 scope.ReplaceTemporaryTable(view) 393 } else if view.FileInfo.IsFile() { 394 scope.Tx.CachedViews.Set(view) 395 } 396 397 return view.FileInfo, insertRecords, err 398 } 399 400 func Update(ctx context.Context, scope *ReferenceScope, query parser.UpdateQuery) ([]*FileInfo, []int, error) { 401 queryScope := scope.CreateNode() 402 defer queryScope.CloseCurrentNode() 403 404 if query.WithClause != nil { 405 if err := queryScope.LoadInlineTable(ctx, query.WithClause.(parser.WithClause)); err != nil { 406 return nil, nil, err 407 } 408 } 409 410 if query.FromClause == nil { 411 query.FromClause = parser.FromClause{Tables: query.Tables} 412 } 413 414 queryScope.Tx.operationMutex.Lock() 415 defer queryScope.Tx.operationMutex.Unlock() 416 417 view, err := LoadView(ctx, queryScope, query.FromClause.(parser.FromClause).Tables, true, true) 418 if err != nil { 419 return nil, nil, err 420 } 421 422 if query.WhereClause != nil { 423 if err := view.Where(ctx, queryScope, query.WhereClause.(parser.WhereClause)); err != nil { 424 return nil, nil, err 425 } 426 } 427 428 viewsToUpdate := make(map[string]*View) 429 updatedCount := make(map[string]int) 430 for _, v := range query.Tables { 431 table := v.(parser.Table) 432 tableName, err := ParseTableName(ctx, queryScope, table) 433 if err != nil { 434 return nil, nil, err 435 } 436 if len(tableName.Literal) < 1 { 437 return nil, nil, NewAliasMustBeSpecifiedForUpdateError(table.Object) 438 } 439 440 fpath, err := queryScope.GetAlias(tableName) 441 if err != nil { 442 return nil, nil, err 443 } 444 if len(fpath) < 1 { 445 return nil, nil, NewInlineTableCannotBeUpdatedError(table.Object) 446 } 447 viewKey := strings.ToUpper(tableName.Literal) 448 449 if queryScope.TemporaryTableExists(fpath) { 450 viewsToUpdate[viewKey], _ = queryScope.GetTemporaryTable(parser.Identifier{Literal: fpath}) 451 } else { 452 viewsToUpdate[viewKey], err = queryScope.Tx.CachedViews.Get(fpath) 453 if err != nil { 454 return nil, nil, NewInlineTableCannotBeUpdatedError(table.Object) 455 } 456 } 457 if err = viewsToUpdate[viewKey].Header.Update(tableName.Literal, nil); err != nil { 458 return nil, nil, err 459 } 460 } 461 462 updatesList := make(map[string]map[int]*UintPool) 463 seqScope := queryScope.CreateScopeForSequentialEvaluation(view) 464 for i := range view.RecordSet { 465 seqScope.Records[0].recordIndex = i 466 internalIds := make(map[string]int) 467 setListLen := len(query.SetList) 468 469 for _, uset := range query.SetList { 470 val, err := Evaluate(ctx, seqScope, uset.Value) 471 if err != nil { 472 return nil, nil, err 473 } 474 475 viewref, err := view.FieldViewName(uset.Field) 476 if err != nil { 477 return nil, nil, err 478 } 479 viewref = strings.ToUpper(viewref) 480 481 if _, ok := viewsToUpdate[viewref]; !ok { 482 return nil, nil, NewUpdateFieldNotExistError(uset.Field) 483 } 484 485 var internalId int 486 if id, ok := internalIds[viewref]; ok { 487 internalId = id 488 } else { 489 id, err := view.InternalRecordId(viewref, i) 490 if err != nil { 491 return nil, nil, NewUpdateValueAmbiguousError(uset.Field, uset.Value) 492 } 493 494 internalId = id 495 internalIds[viewref] = internalId 496 } 497 498 fieldIdx, _ := viewsToUpdate[viewref].Header.SearchIndex(uset.Field) 499 if _, ok := updatesList[viewref]; !ok { 500 updatesList[viewref] = make(map[int]*UintPool) 501 } 502 if _, ok := updatesList[viewref][internalId]; !ok { 503 updatesList[viewref][internalId] = NewUintPool(setListLen, LimitToUseUintSlicePool) 504 updatedCount[viewref]++ 505 } 506 if updatesList[viewref][internalId].Exists(uint(fieldIdx)) { 507 return nil, nil, NewUpdateValueAmbiguousError(uset.Field, uset.Value) 508 } 509 updatesList[viewref][internalId].Add(uint(fieldIdx)) 510 viewsToUpdate[viewref].RecordSet[internalId][fieldIdx] = NewCell(val) 511 } 512 } 513 514 fileInfos := make([]*FileInfo, 0) 515 updateRecords := make([]int, 0) 516 for k, v := range viewsToUpdate { 517 if err = v.RestoreHeaderReferences(); err != nil { 518 return nil, nil, err 519 } 520 521 if v.FileInfo.IsInMemoryTable() { 522 scope.ReplaceTemporaryTable(v) 523 } else if v.FileInfo.IsFile() { 524 scope.Tx.CachedViews.Set(v) 525 } 526 527 fileInfos = append(fileInfos, v.FileInfo) 528 updateRecords = append(updateRecords, updatedCount[k]) 529 } 530 531 return fileInfos, updateRecords, nil 532 } 533 534 func Replace(ctx context.Context, scope *ReferenceScope, query parser.ReplaceQuery) (*FileInfo, int, error) { 535 queryScope := scope.CreateNode() 536 defer queryScope.CloseCurrentNode() 537 538 var replaceRecords int 539 540 if query.WithClause != nil { 541 if err := queryScope.LoadInlineTable(ctx, query.WithClause.(parser.WithClause)); err != nil { 542 return nil, replaceRecords, err 543 } 544 } 545 546 tables := []parser.QueryExpression{ 547 query.Table, 548 } 549 550 queryScope.Tx.operationMutex.Lock() 551 defer queryScope.Tx.operationMutex.Unlock() 552 553 view, err := LoadView(ctx, queryScope, tables, true, false) 554 if err != nil { 555 return nil, replaceRecords, err 556 } 557 if !view.IsUpdatable() { 558 return nil, replaceRecords, NewInlineTableCannotBeUpdatedError(query.Table.Object) 559 } 560 561 fields := query.Fields 562 if fields == nil { 563 fields = view.Header.TableColumns() 564 } 565 566 if query.ValuesList != nil { 567 if replaceRecords, err = view.ReplaceValues(ctx, queryScope, fields, query.ValuesList, query.Keys); err != nil { 568 return nil, replaceRecords, err 569 } 570 } else { 571 if replaceRecords, err = view.ReplaceFromQuery(ctx, queryScope, fields, query.Query.(parser.SelectQuery), query.Keys); err != nil { 572 return nil, replaceRecords, err 573 } 574 } 575 576 if err = view.RestoreHeaderReferences(); err != nil { 577 return nil, replaceRecords, err 578 } 579 580 if view.FileInfo.IsInMemoryTable() { 581 scope.ReplaceTemporaryTable(view) 582 } else if view.FileInfo.IsFile() { 583 scope.Tx.CachedViews.Set(view) 584 } 585 586 return view.FileInfo, replaceRecords, err 587 } 588 589 func Delete(ctx context.Context, scope *ReferenceScope, query parser.DeleteQuery) ([]*FileInfo, []int, error) { 590 queryScope := scope.CreateNode() 591 defer queryScope.CloseCurrentNode() 592 593 if query.WithClause != nil { 594 if err := queryScope.LoadInlineTable(ctx, query.WithClause.(parser.WithClause)); err != nil { 595 return nil, nil, err 596 } 597 } 598 599 tables := query.FromClause.Tables 600 if query.Tables == nil { 601 if 1 < len(tables) { 602 return nil, nil, NewDeleteTableNotSpecifiedError(query) 603 } 604 query.Tables = tables 605 } 606 607 queryScope.Tx.operationMutex.Lock() 608 defer queryScope.Tx.operationMutex.Unlock() 609 610 view, err := LoadView(ctx, queryScope, tables, true, true) 611 if err != nil { 612 return nil, nil, err 613 } 614 615 if query.WhereClause != nil { 616 if err := view.Where(ctx, queryScope, query.WhereClause.(parser.WhereClause)); err != nil { 617 return nil, nil, err 618 } 619 } 620 621 viewsToDelete := make(map[string]*View) 622 deletedIndices := make(map[string]map[int]bool) 623 for _, v := range query.Tables { 624 table := v.(parser.Table) 625 tableName, err := ParseTableName(ctx, queryScope, table) 626 if err != nil { 627 return nil, nil, err 628 } 629 if len(tableName.Literal) < 1 { 630 return nil, nil, NewAliasMustBeSpecifiedForUpdateError(table.Object) 631 } 632 633 fpath, err := queryScope.GetAlias(tableName) 634 if err != nil { 635 return nil, nil, err 636 } 637 if len(fpath) < 1 { 638 return nil, nil, NewInlineTableCannotBeUpdatedError(table.Object) 639 } 640 viewKey := strings.ToUpper(tableName.Literal) 641 642 if queryScope.TemporaryTableExists(fpath) { 643 viewsToDelete[viewKey], _ = queryScope.GetTemporaryTable(parser.Identifier{Literal: fpath}) 644 } else { 645 viewsToDelete[viewKey], err = queryScope.Tx.CachedViews.Get(fpath) 646 if err != nil { 647 return nil, nil, NewInlineTableCannotBeUpdatedError(table.Object) 648 } 649 } 650 if err = viewsToDelete[viewKey].Header.Update(tableName.Literal, nil); err != nil { 651 return nil, nil, err 652 } 653 deletedIndices[viewKey] = make(map[int]bool) 654 } 655 656 for i := range view.RecordSet { 657 if ctx.Err() != nil { 658 return nil, nil, ConvertContextError(ctx.Err()) 659 } 660 661 for viewref := range viewsToDelete { 662 internalId, err := view.InternalRecordId(viewref, i) 663 if err != nil { 664 continue 665 } 666 if !deletedIndices[viewref][internalId] { 667 deletedIndices[viewref][internalId] = true 668 } 669 } 670 } 671 672 fileInfos := make([]*FileInfo, 0) 673 deletedCounts := make([]int, 0) 674 for k, v := range viewsToDelete { 675 if ctx.Err() != nil { 676 return nil, nil, ConvertContextError(ctx.Err()) 677 } 678 679 records := make(RecordSet, 0, v.RecordLen()-len(deletedIndices[k])) 680 for i, record := range v.RecordSet { 681 if !deletedIndices[k][i] { 682 records = append(records, record) 683 } 684 } 685 v.RecordSet = records 686 687 if err = v.RestoreHeaderReferences(); err != nil { 688 return nil, nil, err 689 } 690 691 if v.FileInfo.IsInMemoryTable() { 692 scope.ReplaceTemporaryTable(v) 693 } else if v.FileInfo.IsFile() { 694 scope.Tx.CachedViews.Set(v) 695 } 696 697 fileInfos = append(fileInfos, v.FileInfo) 698 deletedCounts = append(deletedCounts, len(deletedIndices[k])) 699 } 700 701 return fileInfos, deletedCounts, nil 702 } 703 704 func CreateTable(ctx context.Context, scope *ReferenceScope, query parser.CreateTable) (*FileInfo, error) { 705 queryScope := scope.CreateNode() 706 defer queryScope.CloseCurrentNode() 707 708 var view *View 709 710 flags := queryScope.Tx.Flags 711 fileInfo, err := NewFileInfoForCreate(query.Table, flags.Repository, flags.ExportOptions.Delimiter, flags.ExportOptions.Encoding) 712 if err != nil { 713 return nil, err 714 } 715 h, err := queryScope.Tx.FileContainer.CreateHandlerForCreate(fileInfo.Path) 716 if err != nil { 717 query.Table.Literal = fileInfo.Path 718 return nil, ConvertFileHandlerError(err, query.Table) 719 } 720 fileInfo.Handler = h 721 722 fileInfo.LineBreak = flags.ExportOptions.LineBreak 723 fileInfo.EncloseAll = flags.ExportOptions.EncloseAll 724 fileInfo.NoHeader = flags.ExportOptions.WithoutHeader 725 fileInfo.PrettyPrint = flags.ExportOptions.PrettyPrint 726 fileInfo.ForUpdate = true 727 728 if query.Query != nil { 729 view, err = Select(ctx, queryScope, query.Query.(parser.SelectQuery)) 730 if err != nil { 731 return nil, appendCompositeError(err, queryScope.Tx.FileContainer.Close(fileInfo.Handler)) 732 } 733 734 if err = view.Header.Update(FormatTableName(fileInfo.Path), query.Fields); err != nil { 735 if _, ok := err.(*FieldLengthNotMatchError); ok { 736 err = NewTableFieldLengthError(query.Query.(parser.SelectQuery), query.Table, len(query.Fields)) 737 } 738 return nil, appendCompositeError(err, queryScope.Tx.FileContainer.Close(fileInfo.Handler)) 739 } 740 } else { 741 fields := make([]string, len(query.Fields)) 742 fieldsMap := make(map[string]bool, len(query.Fields)) 743 for i := range query.Fields { 744 lit := query.Fields[i].(parser.Identifier).Literal 745 ulit := strings.ToUpper(lit) 746 if _, ok := fieldsMap[ulit]; ok { 747 err = NewDuplicateFieldNameError(query.Fields[i].(parser.Identifier)) 748 return nil, appendCompositeError(err, queryScope.Tx.FileContainer.Close(fileInfo.Handler)) 749 } 750 fields[i] = lit 751 fieldsMap[ulit] = true 752 } 753 header := NewHeader(FormatTableName(fileInfo.Path), fields) 754 view = &View{ 755 Header: header, 756 RecordSet: RecordSet{}, 757 } 758 } 759 760 view.FileInfo = fileInfo 761 762 scope.Tx.CachedViews.Set(view) 763 764 return view.FileInfo, nil 765 } 766 767 func AddColumns(ctx context.Context, scope *ReferenceScope, query parser.AddColumns) (*FileInfo, int, error) { 768 queryScope := scope.CreateNode() 769 defer queryScope.CloseCurrentNode() 770 771 if query.Position == nil { 772 query.Position = parser.ColumnPosition{ 773 Position: parser.Token{Token: parser.LAST, Literal: parser.TokenLiteral(parser.LAST)}, 774 } 775 } 776 777 queryScope.Tx.operationMutex.Lock() 778 defer queryScope.Tx.operationMutex.Unlock() 779 780 view, err := LoadViewFromTableIdentifier(ctx, queryScope, query.Table, true, false) 781 if err != nil { 782 return nil, 0, err 783 } 784 if !view.IsUpdatable() { 785 return nil, 0, NewInlineTableCannotBeUpdatedError(query.Table) 786 } 787 788 var insertPos int 789 pos, _ := query.Position.(parser.ColumnPosition) 790 switch pos.Position.Token { 791 case parser.FIRST: 792 insertPos = 0 793 case parser.LAST: 794 insertPos = view.FieldLen() 795 default: 796 idx, err := view.FieldIndex(pos.Column) 797 if err != nil { 798 return nil, 0, err 799 } 800 switch pos.Position.Token { 801 case parser.BEFORE: 802 insertPos = idx 803 default: //parser.AFTER 804 insertPos = idx + 1 805 } 806 } 807 808 newFieldLen := view.FieldLen() + len(query.Columns) 809 columnNames := view.Header.TableColumnNames() 810 columnNamesMap := make(map[string]bool, newFieldLen) 811 for i := range columnNames { 812 columnNamesMap[strings.ToUpper(columnNames[i])] = true 813 } 814 815 fields := make([]string, len(query.Columns)) 816 defaults := make([]parser.QueryExpression, len(query.Columns)) 817 for i, coldef := range query.Columns { 818 ulit := strings.ToUpper(coldef.Column.Literal) 819 if _, ok := columnNamesMap[ulit]; ok { 820 return nil, 0, NewDuplicateFieldNameError(coldef.Column) 821 } 822 fields[i] = coldef.Column.Literal 823 defaults[i] = coldef.Value 824 columnNamesMap[ulit] = true 825 } 826 827 addHeader := NewHeader(FormatTableName(view.FileInfo.Path), fields) 828 header := make(Header, newFieldLen) 829 for i, v := range view.Header { 830 var idx int 831 if i < insertPos { 832 idx = i 833 } else { 834 idx = i + len(fields) 835 } 836 header[idx] = v 837 } 838 for i, v := range addHeader { 839 header[i+insertPos] = v 840 } 841 colNumber := 0 842 for i := range header { 843 colNumber++ 844 header[i].Number = colNumber 845 } 846 847 records := make(RecordSet, view.RecordLen()) 848 849 if err := EvaluateSequentially(ctx, queryScope, view, func(seqScope *ReferenceScope, rIdx int) error { 850 record := make(Record, newFieldLen) 851 for i, cell := range view.RecordSet[rIdx] { 852 var cellIdx int 853 if i < insertPos { 854 cellIdx = i 855 } else { 856 cellIdx = i + len(fields) 857 } 858 record[cellIdx] = cell 859 } 860 861 for i, v := range defaults { 862 if v == nil { 863 v = parser.NewNullValue() 864 } 865 val, e := Evaluate(ctx, seqScope, v) 866 if e != nil { 867 return e 868 } 869 record[i+insertPos] = NewCell(val) 870 } 871 records[rIdx] = record 872 return nil 873 }); err != nil { 874 return nil, 0, err 875 } 876 877 view.Header = header 878 view.RecordSet = records 879 880 if view.FileInfo.IsInMemoryTable() { 881 scope.ReplaceTemporaryTable(view) 882 } else if view.FileInfo.IsFile() { 883 scope.Tx.CachedViews.Set(view) 884 } 885 886 return view.FileInfo, len(fields), err 887 } 888 889 func DropColumns(ctx context.Context, scope *ReferenceScope, query parser.DropColumns) (*FileInfo, int, error) { 890 queryScope := scope.CreateNode() 891 defer queryScope.CloseCurrentNode() 892 893 queryScope.Tx.operationMutex.Lock() 894 defer queryScope.Tx.operationMutex.Unlock() 895 896 view, err := LoadViewFromTableIdentifier(ctx, queryScope, query.Table, true, false) 897 if err != nil { 898 return nil, 0, err 899 } 900 if !view.IsUpdatable() { 901 return nil, 0, NewInlineTableCannotBeUpdatedError(query.Table) 902 } 903 904 dropIndices := NewUintPool(len(query.Columns), LimitToUseUintSlicePool) 905 for _, v := range query.Columns { 906 idx, err := view.FieldIndex(v) 907 if err != nil { 908 return nil, 0, err 909 } 910 if !dropIndices.Exists(uint(idx)) { 911 dropIndices.Add(uint(idx)) 912 } 913 } 914 915 view.selectFields = []int{} 916 for i := 0; i < view.FieldLen(); i++ { 917 if view.Header[i].IsFromTable && !dropIndices.Exists(uint(i)) { 918 view.selectFields = append(view.selectFields, i) 919 } 920 } 921 922 if err = view.Fix(ctx, scope.Tx.Flags); err != nil { 923 return nil, 0, err 924 } 925 926 if view.FileInfo.IsInMemoryTable() { 927 scope.ReplaceTemporaryTable(view) 928 } else if view.FileInfo.IsFile() { 929 scope.Tx.CachedViews.Set(view) 930 } 931 932 return view.FileInfo, dropIndices.Len(), err 933 934 } 935 936 func RenameColumn(ctx context.Context, scope *ReferenceScope, query parser.RenameColumn) (*FileInfo, error) { 937 queryScope := scope.CreateNode() 938 defer queryScope.CloseCurrentNode() 939 940 queryScope.Tx.operationMutex.Lock() 941 defer queryScope.Tx.operationMutex.Unlock() 942 943 view, err := LoadViewFromTableIdentifier(ctx, queryScope, query.Table, true, false) 944 if err != nil { 945 return nil, err 946 } 947 if !view.IsUpdatable() { 948 return nil, NewInlineTableCannotBeUpdatedError(query.Table) 949 } 950 951 columnNames := view.Header.TableColumnNames() 952 columnNamesMap := make(map[string]bool, len(columnNames)) 953 for i := range columnNames { 954 columnNamesMap[strings.ToUpper(columnNames[i])] = true 955 } 956 if _, ok := columnNamesMap[strings.ToUpper(query.New.Literal)]; ok { 957 return nil, NewDuplicateFieldNameError(query.New) 958 } 959 960 idx, err := view.FieldIndex(query.Old) 961 if err != nil { 962 return nil, err 963 } 964 965 view.Header[idx].Column = query.New.Literal 966 967 if view.FileInfo.IsInMemoryTable() { 968 scope.ReplaceTemporaryTable(view) 969 } else if view.FileInfo.IsFile() { 970 scope.Tx.CachedViews.Set(view) 971 } 972 973 return view.FileInfo, err 974 } 975 976 func SetTableAttribute(ctx context.Context, scope *ReferenceScope, query parser.SetTableAttribute) (*FileInfo, string, error) { 977 var log string 978 979 queryScope := scope.CreateNode() 980 defer queryScope.CloseCurrentNode() 981 982 queryScope.Tx.operationMutex.Lock() 983 defer queryScope.Tx.operationMutex.Unlock() 984 985 view, err := LoadViewFromTableIdentifier(ctx, queryScope, query.Table, true, false) 986 if err != nil { 987 return nil, log, err 988 } 989 if !view.FileInfo.IsFile() { 990 return nil, log, NewNotTableError(query.Table) 991 } 992 993 var p value.Primary 994 if ident, ok := query.Value.(parser.Identifier); ok { 995 p = value.NewString(ident.Literal) 996 } else { 997 p, err = Evaluate(ctx, scope, query.Value) 998 if err != nil { 999 return nil, log, err 1000 } 1001 } 1002 1003 fileInfo := view.FileInfo 1004 attr := strings.ToUpper(query.Attribute.Literal) 1005 switch attr { 1006 case TableDelimiter, TableDelimiterPositions, TableFormat, TableEncoding, TableLineBreak, TableJsonEscape: 1007 s := value.ToString(p) 1008 if value.IsNull(s) { 1009 return nil, log, NewTableAttributeValueNotAllowedFormatError(query) 1010 } 1011 switch attr { 1012 case TableDelimiter: 1013 err = fileInfo.SetDelimiter(s.(*value.String).Raw()) 1014 case TableDelimiterPositions: 1015 err = fileInfo.SetDelimiterPositions(s.(*value.String).Raw()) 1016 case TableFormat: 1017 err = fileInfo.SetFormat(s.(*value.String).Raw()) 1018 case TableEncoding: 1019 err = fileInfo.SetEncoding(s.(*value.String).Raw()) 1020 case TableLineBreak: 1021 err = fileInfo.SetLineBreak(s.(*value.String).Raw()) 1022 case TableJsonEscape: 1023 err = fileInfo.SetJsonEscape(s.(*value.String).Raw()) 1024 } 1025 value.Discard(s) 1026 case TableHeader, TableEncloseAll, TablePrettyPrint: 1027 b := value.ToBoolean(p) 1028 if value.IsNull(b) { 1029 return nil, log, NewTableAttributeValueNotAllowedFormatError(query) 1030 } 1031 switch attr { 1032 case TableHeader: 1033 err = fileInfo.SetNoHeader(!b.(*value.Boolean).Raw()) 1034 case TableEncloseAll: 1035 err = fileInfo.SetEncloseAll(b.(*value.Boolean).Raw()) 1036 case TablePrettyPrint: 1037 err = fileInfo.SetPrettyPrint(b.(*value.Boolean).Raw()) 1038 } 1039 default: 1040 return nil, log, NewInvalidTableAttributeNameError(query.Attribute) 1041 } 1042 1043 if err != nil { 1044 if _, ok := err.(*TableAttributeUnchangedError); ok { 1045 return nil, log, err 1046 } 1047 return nil, log, NewInvalidTableAttributeValueError(query, err.Error()) 1048 } 1049 1050 w := scope.Tx.CreateDocumentWriter() 1051 w.WriteColorWithoutLineBreak("Path: ", option.LableEffect) 1052 w.WriteColorWithoutLineBreak(fileInfo.Path, option.ObjectEffect) 1053 w.NewLine() 1054 writeTableAttribute(w, scope.Tx.Flags, fileInfo) 1055 w.NewLine() 1056 1057 w.Title1 = "Attributes Updated in" 1058 if i, ok := query.Table.(parser.Identifier); ok { 1059 w.Title2 = i.Literal 1060 } else if to, ok := query.Table.(parser.FormatSpecifiedFunction); ok { 1061 if pi, ok := to.Path.(parser.Identifier); ok { 1062 w.Title2 = pi.Literal 1063 } 1064 } 1065 w.Title2Effect = option.IdentifierEffect 1066 log = "\n" + w.String() + "\n" 1067 1068 scope.Tx.CachedViews.Set(view) 1069 return view.FileInfo, log, err 1070 }