2
0

result.go 3.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152
  1. package executor
  2. import (
  3. "fmt"
  4. "strings"
  5. )
  6. // Result represents the result of executing a SQL statement.
  7. type Result struct {
  8. Columns []string // Column names
  9. ColumnTypes []string // Column types (for type inference)
  10. Rows [][]interface{} // Row data
  11. RowCount int // Number of affected/returned rows
  12. RowsAffected int64 // Number of rows affected (for INSERT/UPDATE/DELETE)
  13. LastInsertID int64 // Last insert ID (for INSERT with AUTOINCREMENT)
  14. CommandTag string // Command type (SELECT, INSERT, UPDATE, DELETE, etc.)
  15. LSN uint64 // Commit LSN for a committed transaction (0 when none)
  16. }
  17. // NewResult creates a new empty result.
  18. func NewResult(tag string) *Result {
  19. return &Result{
  20. CommandTag: tag,
  21. Rows: make([][]interface{}, 0),
  22. }
  23. }
  24. // AddColumn adds a column to the result.
  25. func (r *Result) AddColumn(name string) {
  26. r.Columns = append(r.Columns, name)
  27. }
  28. // AddRow adds a row to the result.
  29. func (r *Result) AddRow(values ...interface{}) {
  30. for i, v := range values {
  31. if jt, ok := v.(jsonText); ok {
  32. values[i] = string(jt)
  33. }
  34. }
  35. r.Rows = append(r.Rows, values)
  36. r.RowCount = len(r.Rows)
  37. }
  38. // SetRowCount sets the row count (for non-SELECT queries).
  39. func (r *Result) SetRowCount(count int) {
  40. r.RowCount = count
  41. r.RowsAffected = int64(count)
  42. }
  43. // SetLastInsertID sets the last insert ID.
  44. func (r *Result) SetLastInsertID(id int64) {
  45. r.LastInsertID = id
  46. }
  47. // AddColumnWithType adds a column with its type to the result.
  48. func (r *Result) AddColumnWithType(name, colType string) {
  49. r.Columns = append(r.Columns, name)
  50. r.ColumnTypes = append(r.ColumnTypes, colType)
  51. }
  52. // GetColumnType returns the type for a column index.
  53. func (r *Result) GetColumnType(idx int) string {
  54. if idx < len(r.ColumnTypes) {
  55. return r.ColumnTypes[idx]
  56. }
  57. return "ANY"
  58. }
  59. // String returns a string representation of the result.
  60. func (r *Result) String() string {
  61. var sb strings.Builder
  62. if len(r.Columns) > 0 {
  63. // Calculate column widths
  64. widths := make([]int, len(r.Columns))
  65. for i, col := range r.Columns {
  66. widths[i] = len(col)
  67. }
  68. for _, row := range r.Rows {
  69. for i, val := range row {
  70. if i < len(widths) {
  71. w := len(fmt.Sprintf("%v", val))
  72. if w > widths[i] {
  73. widths[i] = w
  74. }
  75. }
  76. }
  77. }
  78. // Print header
  79. for i, col := range r.Columns {
  80. if i > 0 {
  81. sb.WriteString(" | ")
  82. }
  83. sb.WriteString(padRight(col, widths[i]))
  84. }
  85. sb.WriteString("\n")
  86. // Print separator
  87. for i, w := range widths {
  88. if i > 0 {
  89. sb.WriteString("-+-")
  90. }
  91. sb.WriteString(strings.Repeat("-", w))
  92. }
  93. sb.WriteString("\n")
  94. // Print rows
  95. for _, row := range r.Rows {
  96. for i, val := range row {
  97. if i > 0 {
  98. sb.WriteString(" | ")
  99. }
  100. if i < len(widths) {
  101. sb.WriteString(padRight(fmt.Sprintf("%v", val), widths[i]))
  102. }
  103. }
  104. sb.WriteString("\n")
  105. }
  106. }
  107. // Print row count
  108. sb.WriteString(fmt.Sprintf("(%d row", r.RowCount))
  109. if r.RowCount != 1 {
  110. sb.WriteString("s")
  111. }
  112. sb.WriteString(")\n")
  113. return sb.String()
  114. }
  115. func padRight(s string, width int) string {
  116. if len(s) >= width {
  117. return s
  118. }
  119. return s + strings.Repeat(" ", width-len(s))
  120. }
  121. // ToMaps converts the result to a slice of maps.
  122. func (r *Result) ToMaps() []map[string]interface{} {
  123. result := make([]map[string]interface{}, len(r.Rows))
  124. for i, row := range r.Rows {
  125. m := make(map[string]interface{})
  126. for j, col := range r.Columns {
  127. if j < len(row) {
  128. m[col] = row[j]
  129. }
  130. }
  131. result[i] = m
  132. }
  133. return result
  134. }