github.com/mithrandie/csvq@v1.18.1/lib/query/transaction.go (about) 1 package query 2 3 import ( 4 "context" 5 "errors" 6 "fmt" 7 "io" 8 "net/http" 9 "strconv" 10 "strings" 11 "sync" 12 "time" 13 14 "github.com/mithrandie/csvq/lib/doc" 15 "github.com/mithrandie/csvq/lib/file" 16 "github.com/mithrandie/csvq/lib/option" 17 "github.com/mithrandie/csvq/lib/parser" 18 "github.com/mithrandie/csvq/lib/value" 19 20 "github.com/mithrandie/go-text/color" 21 "github.com/mithrandie/go-text/fixedlen" 22 ) 23 24 type UrlResource struct { 25 MimeType string 26 Data []byte 27 } 28 29 func NewUrlResource(res *http.Response) (*UrlResource, error) { 30 contentType := res.Header.Get("Content-Type") 31 contentItems := strings.Split(contentType, ";") 32 mimeType := contentItems[0] 33 34 body, err := io.ReadAll(res.Body) 35 if err != nil { 36 return nil, NewSystemError(err.Error()) 37 } 38 39 return &UrlResource{ 40 MimeType: mimeType, 41 Data: body, 42 }, nil 43 } 44 45 type Transaction struct { 46 Session *Session 47 48 Environment *option.Environment 49 Palette *color.Palette 50 Flags *option.Flags 51 52 WaitTimeout time.Duration 53 RetryDelay time.Duration 54 FileContainer *file.Container 55 56 CachedViews ViewMap 57 UncommittedViews UncommittedViews 58 59 UrlCache map[string]*UrlResource 60 61 operationMutex *sync.Mutex 62 viewLoadingMutex *sync.Mutex 63 stdinIsLocked bool 64 65 flagMutex *sync.RWMutex 66 67 PreparedStatements PreparedStatementMap 68 69 SelectedViews []*View 70 AffectedRows int 71 72 AutoCommit bool 73 } 74 75 func NewTransaction(ctx context.Context, defaultWaitTimeout time.Duration, retryDelay time.Duration, session *Session) (*Transaction, error) { 76 environment, err := option.NewEnvironment(ctx, defaultWaitTimeout, retryDelay) 77 if err != nil { 78 return nil, ConvertLoadConfigurationError(err) 79 } 80 81 flags, err := option.NewFlags(environment) 82 if err != nil { 83 return nil, ConvertLoadConfigurationError(err) 84 } 85 86 palette, err := option.NewPalette(environment) 87 if err != nil { 88 return nil, ConvertLoadConfigurationError(err) 89 } 90 91 palette.Disable() 92 93 return &Transaction{ 94 Session: session, 95 Environment: environment, 96 Palette: palette, 97 Flags: flags, 98 WaitTimeout: file.DefaultWaitTimeout, 99 RetryDelay: file.DefaultRetryDelay, 100 FileContainer: file.NewContainer(), 101 CachedViews: NewViewMap(), 102 UncommittedViews: NewUncommittedViews(), 103 UrlCache: make(map[string]*UrlResource, 5), 104 operationMutex: &sync.Mutex{}, 105 viewLoadingMutex: &sync.Mutex{}, 106 stdinIsLocked: false, 107 flagMutex: &sync.RWMutex{}, 108 PreparedStatements: NewPreparedStatementMap(), 109 SelectedViews: nil, 110 AffectedRows: 0, 111 AutoCommit: false, 112 }, nil 113 } 114 115 func (tx *Transaction) UpdateWaitTimeout(waitTimeout float64, retryDelay time.Duration) { 116 d, err := time.ParseDuration(strconv.FormatFloat(waitTimeout, 'f', -1, 64) + "s") 117 if err != nil { 118 d = file.DefaultWaitTimeout 119 } 120 121 tx.WaitTimeout = d 122 tx.RetryDelay = retryDelay 123 tx.Flags.SetWaitTimeout(waitTimeout) 124 } 125 126 func (tx *Transaction) UseColor(useColor bool) { 127 if useColor { 128 tx.Palette.Enable() 129 } else { 130 tx.Palette.Disable() 131 } 132 tx.Flags.SetColor(useColor) 133 } 134 135 func (tx *Transaction) Commit(ctx context.Context, scope *ReferenceScope, expr parser.Expression) error { 136 tx.operationMutex.Lock() 137 defer tx.operationMutex.Unlock() 138 139 createdFiles, updatedFiles := tx.UncommittedViews.UncommittedFiles() 140 141 createFileInfo := make([]*FileInfo, 0, len(createdFiles)) 142 updateFileInfo := make([]*FileInfo, 0, len(updatedFiles)) 143 144 if 0 < len(createdFiles) { 145 for _, fileInfo := range createdFiles { 146 view, _ := tx.CachedViews.Get(fileInfo.IdentifiedPath()) 147 148 fp, _ := view.FileInfo.Handler.FileForUpdate() 149 if err := fp.Truncate(0); err != nil { 150 return NewSystemError(err.Error()) 151 } 152 if _, err := fp.Seek(0, io.SeekStart); err != nil { 153 return NewSystemError(err.Error()) 154 } 155 156 if _, err := EncodeView(ctx, fp, view, fileInfo.ExportOptions(tx), tx.Palette); err != nil { 157 return NewCommitError(expr, err.Error()) 158 } 159 160 if !tx.Flags.ExportOptions.StripEndingLineBreak && !(fileInfo.Format == option.FIXED && fileInfo.SingleLine) { 161 if _, err := fp.Write([]byte(tx.Flags.ExportOptions.LineBreak.Value())); err != nil { 162 return NewCommitError(expr, err.Error()) 163 } 164 } 165 166 createFileInfo = append(createFileInfo, view.FileInfo) 167 } 168 } 169 170 if 0 < len(updatedFiles) { 171 for _, fileInfo := range updatedFiles { 172 view, _ := tx.CachedViews.Get(fileInfo.IdentifiedPath()) 173 174 fp, _ := view.FileInfo.Handler.FileForUpdate() 175 if err := fp.Truncate(0); err != nil { 176 return NewSystemError(err.Error()) 177 } 178 if _, err := fp.Seek(0, io.SeekStart); err != nil { 179 return NewSystemError(err.Error()) 180 } 181 182 if _, err := EncodeView(ctx, fp, view, fileInfo.ExportOptions(tx), tx.Palette); err != nil { 183 return NewCommitError(expr, err.Error()) 184 } 185 186 if !tx.Flags.ExportOptions.StripEndingLineBreak && !(fileInfo.Format == option.FIXED && fileInfo.SingleLine) { 187 if _, err := fp.Write([]byte(tx.Flags.ExportOptions.LineBreak.Value())); err != nil { 188 return NewCommitError(expr, err.Error()) 189 } 190 } 191 192 updateFileInfo = append(updateFileInfo, view.FileInfo) 193 } 194 } 195 196 for _, f := range createFileInfo { 197 if err := tx.FileContainer.Commit(f.Handler); err != nil { 198 return NewCommitError(expr, err.Error()) 199 } 200 tx.UncommittedViews.Unset(f) 201 tx.LogNotice(fmt.Sprintf("Commit: file %q is created.", f.Path), tx.Flags.Quiet) 202 } 203 for _, f := range updateFileInfo { 204 if err := tx.FileContainer.Commit(f.Handler); err != nil { 205 return NewCommitError(expr, err.Error()) 206 } 207 tx.UncommittedViews.Unset(f) 208 tx.LogNotice(fmt.Sprintf("Commit: file %q is updated.", f.Path), tx.Flags.Quiet) 209 } 210 211 msglist := scope.StoreTemporaryTable(tx.Session, tx.UncommittedViews.UncommittedTempViews()) 212 if 0 < len(msglist) { 213 tx.LogNotice(strings.Join(msglist, "\n"), tx.quietForTemporaryViews(expr)) 214 } 215 tx.UncommittedViews.Clean() 216 tx.UnlockStdin() 217 if err := tx.ReleaseResources(); err != nil { 218 return NewCommitError(expr, err.Error()) 219 } 220 return nil 221 } 222 223 func (tx *Transaction) Rollback(scope *ReferenceScope, expr parser.Expression) error { 224 tx.operationMutex.Lock() 225 defer tx.operationMutex.Unlock() 226 227 createdFiles, updatedFiles := tx.UncommittedViews.UncommittedFiles() 228 229 if 0 < len(createdFiles) { 230 for _, fileinfo := range createdFiles { 231 tx.LogNotice(fmt.Sprintf("Rollback: file %q is deleted.", fileinfo.Path), tx.Flags.Quiet) 232 } 233 } 234 235 if 0 < len(updatedFiles) { 236 for _, fileinfo := range updatedFiles { 237 tx.LogNotice(fmt.Sprintf("Rollback: file %q is restored.", fileinfo.Path), tx.Flags.Quiet) 238 } 239 } 240 241 if scope != nil { 242 msglist := scope.RestoreTemporaryTable(tx.UncommittedViews.UncommittedTempViews()) 243 if 0 < len(msglist) { 244 tx.LogNotice(strings.Join(msglist, "\n"), tx.quietForTemporaryViews(expr)) 245 } 246 } 247 tx.UncommittedViews.Clean() 248 tx.UnlockStdin() 249 if err := tx.ReleaseResources(); err != nil { 250 return NewRollbackError(expr, err.Error()) 251 } 252 return nil 253 } 254 255 func (tx *Transaction) quietForTemporaryViews(expr parser.Expression) bool { 256 return tx.Flags.Quiet || expr == nil 257 } 258 259 func (tx *Transaction) ReleaseResources() error { 260 if err := tx.CachedViews.Clean(tx.FileContainer); err != nil { 261 return err 262 } 263 if err := tx.FileContainer.CloseAll(); err != nil { 264 return err 265 } 266 tx.UnlockStdin() 267 tx.ClearUrlCache() 268 return nil 269 } 270 271 func (tx *Transaction) ReleaseResourcesWithErrors() error { 272 var errs []error 273 if err := tx.CachedViews.CleanWithErrors(tx.FileContainer); err != nil { 274 errs = append(errs, err.(*file.ForcedUnlockError).Errors...) 275 } 276 if err := tx.FileContainer.CloseAllWithErrors(); err != nil { 277 errs = append(errs, err.(*file.ForcedUnlockError).Errors...) 278 } 279 tx.UnlockStdin() 280 tx.ClearUrlCache() 281 return file.NewForcedUnlockError(errs) 282 } 283 284 func (tx *Transaction) LockStdinContext(ctx context.Context) error { 285 tctx, cancel := file.GetTimeoutContext(ctx, tx.WaitTimeout) 286 defer cancel() 287 288 err := tx.Session.stdinLocker.LockContext(tctx) 289 if err == nil { 290 tx.stdinIsLocked = true 291 } 292 return err 293 } 294 295 func (tx *Transaction) UnlockStdin() { 296 if tx.stdinIsLocked { 297 tx.stdinIsLocked = false 298 _ = tx.Session.stdinLocker.Unlock() 299 } 300 } 301 302 func (tx *Transaction) RLockStdinContext(ctx context.Context) error { 303 tctx, cancel := file.GetTimeoutContext(ctx, tx.WaitTimeout) 304 defer cancel() 305 306 return tx.Session.stdinLocker.RLockContext(tctx) 307 } 308 309 func (tx *Transaction) RUnlockStdin() { 310 _ = tx.Session.stdinLocker.RUnlock() 311 } 312 313 func (tx *Transaction) ClearUrlCache() { 314 for k := range tx.UrlCache { 315 delete(tx.UrlCache, k) 316 } 317 } 318 319 func (tx *Transaction) CreateDocumentWriter() *doc.Writer { 320 return doc.NewWriter(tx.Session.ScreenWidth(), tx.Flags, tx.Palette) 321 } 322 323 func (tx *Transaction) Error(s string) string { 324 if tx.Palette != nil { 325 return tx.Palette.Render(option.ErrorEffect, s) 326 } 327 return s 328 } 329 330 func (tx *Transaction) Warn(s string) string { 331 if tx.Palette != nil { 332 return tx.Palette.Render(option.WarnEffect, s) 333 } 334 return s 335 } 336 337 func (tx *Transaction) Notice(s string) string { 338 if tx.Palette != nil { 339 return tx.Palette.Render(option.NoticeEffect, s) 340 } 341 return s 342 } 343 344 func (tx *Transaction) Log(log string, quiet bool) { 345 if !quiet { 346 if err := tx.Session.WriteToStdoutWithLineBreak(log); err != nil { 347 println(err.Error()) 348 } 349 } 350 } 351 352 func (tx *Transaction) LogNotice(log string, quiet bool) { 353 if !quiet { 354 if err := tx.Session.WriteToStdoutWithLineBreak(tx.Notice(log)); err != nil { 355 println(err.Error()) 356 } 357 } 358 } 359 360 func (tx *Transaction) LogWarn(log string, quiet bool) { 361 if !quiet { 362 if err := tx.Session.WriteToStdoutWithLineBreak(tx.Warn(log)); err != nil { 363 println(err.Error()) 364 } 365 } 366 } 367 368 func (tx *Transaction) LogError(log string) { 369 if err := tx.Session.WriteToStderrWithLineBreak(tx.Error(log)); err != nil { 370 println(err.Error()) 371 } 372 } 373 374 var errNotAllowdFlagFormat = errors.New("not allowed flag format") 375 var errInvalidFlagName = errors.New("invalid flag name") 376 377 func (tx *Transaction) SetFormatFlag(value interface{}, outFile string) error { 378 return tx.setFlag(option.FormatFlag, value, outFile) 379 } 380 381 func (tx *Transaction) SetFlag(key string, value interface{}) error { 382 return tx.setFlag(key, value, "") 383 } 384 385 func (tx *Transaction) setFlag(key string, value interface{}, outFile string) error { 386 tx.flagMutex.Lock() 387 defer tx.flagMutex.Unlock() 388 389 var err error 390 391 switch strings.ToUpper(key) { 392 case option.RepositoryFlag: 393 if s, ok := value.(string); ok { 394 err = tx.Flags.SetRepository(s) 395 } else { 396 err = errNotAllowdFlagFormat 397 } 398 case option.TimezoneFlag: 399 if s, ok := value.(string); ok { 400 err = tx.Flags.SetLocation(s) 401 } else { 402 err = errNotAllowdFlagFormat 403 } 404 case option.DatetimeFormatFlag: 405 if s, ok := value.(string); ok { 406 tx.Flags.SetDatetimeFormat(s) 407 } else { 408 err = errNotAllowdFlagFormat 409 } 410 case option.AnsiQuotesFlag: 411 if b, ok := value.(bool); ok { 412 tx.Flags.SetAnsiQuotes(b) 413 } else { 414 err = errNotAllowdFlagFormat 415 } 416 case option.StrictEqualFlag: 417 if b, ok := value.(bool); ok { 418 tx.Flags.SetStrictEqual(b) 419 } else { 420 err = errNotAllowdFlagFormat 421 } 422 case option.WaitTimeoutFlag: 423 if f, ok := value.(float64); ok { 424 tx.UpdateWaitTimeout(f, file.DefaultRetryDelay) 425 } else { 426 err = errNotAllowdFlagFormat 427 } 428 case option.ImportFormatFlag: 429 if s, ok := value.(string); ok { 430 err = tx.Flags.SetImportFormat(s) 431 } else { 432 err = errNotAllowdFlagFormat 433 } 434 case option.DelimiterFlag: 435 if s, ok := value.(string); ok { 436 err = tx.Flags.SetDelimiter(s) 437 } else { 438 err = errNotAllowdFlagFormat 439 } 440 case option.AllowUnevenFieldsFlag: 441 if b, ok := value.(bool); ok { 442 tx.Flags.SetAllowUnevenFields(b) 443 } else { 444 err = errNotAllowdFlagFormat 445 } 446 case option.DelimiterPositionsFlag: 447 if s, ok := value.(string); ok { 448 err = tx.Flags.SetDelimiterPositions(s) 449 } else { 450 err = errNotAllowdFlagFormat 451 } 452 case option.JsonQueryFlag: 453 if s, ok := value.(string); ok { 454 tx.Flags.SetJsonQuery(s) 455 } else { 456 err = errNotAllowdFlagFormat 457 } 458 case option.EncodingFlag: 459 if s, ok := value.(string); ok { 460 err = tx.Flags.SetEncoding(s) 461 } else { 462 err = errNotAllowdFlagFormat 463 } 464 case option.NoHeaderFlag: 465 if b, ok := value.(bool); ok { 466 tx.Flags.SetNoHeader(b) 467 } else { 468 err = errNotAllowdFlagFormat 469 } 470 case option.WithoutNullFlag: 471 if b, ok := value.(bool); ok { 472 tx.Flags.SetWithoutNull(b) 473 } else { 474 err = errNotAllowdFlagFormat 475 } 476 case option.FormatFlag: 477 if s, ok := value.(string); ok { 478 err = tx.Flags.SetFormat(s, outFile, tx.Session.CanOutputToPipe) 479 } else { 480 err = errNotAllowdFlagFormat 481 } 482 case option.ExportEncodingFlag: 483 if s, ok := value.(string); ok { 484 err = tx.Flags.SetWriteEncoding(s) 485 } else { 486 err = errNotAllowdFlagFormat 487 } 488 case option.ExportDelimiterFlag: 489 if s, ok := value.(string); ok { 490 err = tx.Flags.SetWriteDelimiter(s) 491 } else { 492 err = errNotAllowdFlagFormat 493 } 494 case option.ExportDelimiterPositionsFlag: 495 if s, ok := value.(string); ok { 496 err = tx.Flags.SetWriteDelimiterPositions(s) 497 } else { 498 err = errNotAllowdFlagFormat 499 } 500 case option.WithoutHeaderFlag: 501 if b, ok := value.(bool); ok { 502 tx.Flags.SetWithoutHeader(b) 503 } else { 504 err = errNotAllowdFlagFormat 505 } 506 case option.LineBreakFlag: 507 if s, ok := value.(string); ok { 508 err = tx.Flags.SetLineBreak(s) 509 } else { 510 err = errNotAllowdFlagFormat 511 } 512 case option.EncloseAllFlag: 513 if b, ok := value.(bool); ok { 514 tx.Flags.SetEncloseAll(b) 515 } else { 516 err = errNotAllowdFlagFormat 517 } 518 case option.JsonEscapeFlag: 519 if s, ok := value.(string); ok { 520 err = tx.Flags.SetJsonEscape(s) 521 } else { 522 err = errNotAllowdFlagFormat 523 } 524 case option.PrettyPrintFlag: 525 if b, ok := value.(bool); ok { 526 tx.Flags.SetPrettyPrint(b) 527 } else { 528 err = errNotAllowdFlagFormat 529 } 530 case option.ScientificNotationFlag: 531 if b, ok := value.(bool); ok { 532 tx.Flags.SetScientificNotation(b) 533 } else { 534 err = errNotAllowdFlagFormat 535 } 536 case option.StripEndingLineBreakFlag: 537 if b, ok := value.(bool); ok { 538 tx.Flags.SetStripEndingLineBreak(b) 539 } else { 540 err = errNotAllowdFlagFormat 541 } 542 case option.EastAsianEncodingFlag: 543 if b, ok := value.(bool); ok { 544 tx.Flags.SetEastAsianEncoding(b) 545 } else { 546 err = errNotAllowdFlagFormat 547 } 548 case option.CountDiacriticalSignFlag: 549 if b, ok := value.(bool); ok { 550 tx.Flags.SetCountDiacriticalSign(b) 551 } else { 552 err = errNotAllowdFlagFormat 553 } 554 case option.CountFormatCodeFlag: 555 if b, ok := value.(bool); ok { 556 tx.Flags.SetCountFormatCode(b) 557 } else { 558 err = errNotAllowdFlagFormat 559 } 560 case option.ColorFlag: 561 if b, ok := value.(bool); ok { 562 tx.UseColor(b) 563 } else { 564 err = errNotAllowdFlagFormat 565 } 566 case option.QuietFlag: 567 if b, ok := value.(bool); ok { 568 tx.Flags.SetQuiet(b) 569 } else { 570 err = errNotAllowdFlagFormat 571 } 572 case option.LimitRecursion: 573 if i, ok := value.(int64); ok { 574 tx.Flags.SetLimitRecursion(i) 575 } else { 576 err = errNotAllowdFlagFormat 577 } 578 case option.CPUFlag: 579 if i, ok := value.(int64); ok { 580 tx.Flags.SetCPU(int(i)) 581 } else { 582 err = errNotAllowdFlagFormat 583 } 584 case option.StatsFlag: 585 if b, ok := value.(bool); ok { 586 tx.Flags.SetStats(b) 587 } else { 588 err = errNotAllowdFlagFormat 589 } 590 default: 591 err = errInvalidFlagName 592 } 593 594 return err 595 } 596 597 func (tx *Transaction) GetFlag(key string) (value.Primary, bool) { 598 tx.flagMutex.RLock() 599 defer tx.flagMutex.RUnlock() 600 601 var val value.Primary 602 var ok = true 603 604 switch strings.ToUpper(key) { 605 case option.RepositoryFlag: 606 val = value.NewString(tx.Flags.Repository) 607 case option.TimezoneFlag: 608 val = value.NewString(tx.Flags.Location) 609 case option.DatetimeFormatFlag: 610 s := "" 611 if 0 < len(tx.Flags.DatetimeFormat) { 612 list := make([]string, 0, len(tx.Flags.DatetimeFormat)) 613 for _, f := range tx.Flags.DatetimeFormat { 614 list = append(list, "\""+f+"\"") 615 } 616 s = "[" + strings.Join(list, ", ") + "]" 617 } 618 val = value.NewString(s) 619 case option.AnsiQuotesFlag: 620 val = value.NewBoolean(tx.Flags.AnsiQuotes) 621 case option.StrictEqualFlag: 622 val = value.NewBoolean(tx.Flags.StrictEqual) 623 case option.WaitTimeoutFlag: 624 val = value.NewFloat(tx.Flags.WaitTimeout) 625 case option.ImportFormatFlag: 626 val = value.NewString(tx.Flags.ImportOptions.Format.String()) 627 case option.DelimiterFlag: 628 val = value.NewString(string(tx.Flags.ImportOptions.Delimiter)) 629 case option.AllowUnevenFieldsFlag: 630 val = value.NewBoolean(tx.Flags.ImportOptions.AllowUnevenFields) 631 case option.DelimiterPositionsFlag: 632 s := fixedlen.DelimiterPositions(tx.Flags.ImportOptions.DelimiterPositions).String() 633 if tx.Flags.ImportOptions.SingleLine { 634 s = "S" + s 635 } 636 val = value.NewString(s) 637 case option.JsonQueryFlag: 638 val = value.NewString(tx.Flags.ImportOptions.JsonQuery) 639 case option.EncodingFlag: 640 val = value.NewString(tx.Flags.ImportOptions.Encoding.String()) 641 case option.NoHeaderFlag: 642 val = value.NewBoolean(tx.Flags.ImportOptions.NoHeader) 643 case option.WithoutNullFlag: 644 val = value.NewBoolean(tx.Flags.ImportOptions.WithoutNull) 645 case option.FormatFlag: 646 val = value.NewString(tx.Flags.ExportOptions.Format.String()) 647 case option.ExportEncodingFlag: 648 val = value.NewString(tx.Flags.ExportOptions.Encoding.String()) 649 case option.ExportDelimiterFlag: 650 val = value.NewString(string(tx.Flags.ExportOptions.Delimiter)) 651 case option.ExportDelimiterPositionsFlag: 652 s := fixedlen.DelimiterPositions(tx.Flags.ExportOptions.DelimiterPositions).String() 653 if tx.Flags.ExportOptions.SingleLine { 654 s = "S" + s 655 } 656 val = value.NewString(s) 657 case option.WithoutHeaderFlag: 658 val = value.NewBoolean(tx.Flags.ExportOptions.WithoutHeader) 659 case option.LineBreakFlag: 660 val = value.NewString(tx.Flags.ExportOptions.LineBreak.String()) 661 case option.EncloseAllFlag: 662 val = value.NewBoolean(tx.Flags.ExportOptions.EncloseAll) 663 case option.JsonEscapeFlag: 664 val = value.NewString(option.JsonEscapeTypeToString(tx.Flags.ExportOptions.JsonEscape)) 665 case option.PrettyPrintFlag: 666 val = value.NewBoolean(tx.Flags.ExportOptions.PrettyPrint) 667 case option.ScientificNotationFlag: 668 val = value.NewBoolean(tx.Flags.ExportOptions.ScientificNotation) 669 case option.StripEndingLineBreakFlag: 670 val = value.NewBoolean(tx.Flags.ExportOptions.StripEndingLineBreak) 671 case option.EastAsianEncodingFlag: 672 val = value.NewBoolean(tx.Flags.ExportOptions.EastAsianEncoding) 673 case option.CountDiacriticalSignFlag: 674 val = value.NewBoolean(tx.Flags.ExportOptions.CountDiacriticalSign) 675 case option.CountFormatCodeFlag: 676 val = value.NewBoolean(tx.Flags.ExportOptions.CountFormatCode) 677 case option.ColorFlag: 678 val = value.NewBoolean(tx.Flags.ExportOptions.Color) 679 case option.QuietFlag: 680 val = value.NewBoolean(tx.Flags.Quiet) 681 case option.LimitRecursion: 682 val = value.NewInteger(tx.Flags.LimitRecursion) 683 case option.CPUFlag: 684 val = value.NewInteger(int64(tx.Flags.CPU)) 685 case option.StatsFlag: 686 val = value.NewBoolean(tx.Flags.Stats) 687 default: 688 ok = false 689 } 690 return val, ok 691 }