ddlmod_parse_all_columns.go 2.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117
  1. package sqlite
  2. import (
  3. "errors"
  4. "fmt"
  5. )
  6. type parseAllColumnsState int
  7. const (
  8. parseAllColumnsState_NONE parseAllColumnsState = iota
  9. parseAllColumnsState_Beginning
  10. parseAllColumnsState_ReadingRawName
  11. parseAllColumnsState_ReadingQuotedName
  12. parseAllColumnsState_EndOfName
  13. parseAllColumnsState_State_End
  14. )
  15. func parseAllColumns(in string) ([]string, error) {
  16. s := []rune(in)
  17. columns := make([]string, 0)
  18. state := parseAllColumnsState_NONE
  19. quote := rune(0)
  20. name := make([]rune, 0)
  21. for i := 0; i < len(s); i++ {
  22. switch state {
  23. case parseAllColumnsState_NONE:
  24. if s[i] == '(' {
  25. state = parseAllColumnsState_Beginning
  26. }
  27. case parseAllColumnsState_Beginning:
  28. if isSpace(s[i]) {
  29. continue
  30. }
  31. if isQuote(s[i]) {
  32. state = parseAllColumnsState_ReadingQuotedName
  33. quote = s[i]
  34. continue
  35. }
  36. if s[i] == '[' {
  37. state = parseAllColumnsState_ReadingQuotedName
  38. quote = ']'
  39. continue
  40. } else if s[i] == ')' {
  41. return columns, fmt.Errorf("unexpected token: %s", string(s[i]))
  42. }
  43. state = parseAllColumnsState_ReadingRawName
  44. name = append(name, s[i])
  45. case parseAllColumnsState_ReadingRawName:
  46. if isSeparator(s[i]) {
  47. state = parseAllColumnsState_Beginning
  48. columns = append(columns, string(name))
  49. name = make([]rune, 0)
  50. continue
  51. }
  52. if s[i] == ')' {
  53. state = parseAllColumnsState_State_End
  54. columns = append(columns, string(name))
  55. }
  56. if isQuote(s[i]) {
  57. return nil, fmt.Errorf("unexpected token: %s", string(s[i]))
  58. }
  59. if isSpace(s[i]) {
  60. state = parseAllColumnsState_EndOfName
  61. columns = append(columns, string(name))
  62. name = make([]rune, 0)
  63. continue
  64. }
  65. name = append(name, s[i])
  66. case parseAllColumnsState_ReadingQuotedName:
  67. if s[i] == quote {
  68. // check if quote character is escaped
  69. if i+1 < len(s) && s[i+1] == quote {
  70. name = append(name, quote)
  71. i++
  72. continue
  73. }
  74. state = parseAllColumnsState_EndOfName
  75. columns = append(columns, string(name))
  76. name = make([]rune, 0)
  77. continue
  78. }
  79. name = append(name, s[i])
  80. case parseAllColumnsState_EndOfName:
  81. if isSpace(s[i]) {
  82. continue
  83. }
  84. if isSeparator(s[i]) {
  85. state = parseAllColumnsState_Beginning
  86. continue
  87. }
  88. if s[i] == ')' {
  89. state = parseAllColumnsState_State_End
  90. continue
  91. }
  92. return nil, fmt.Errorf("unexpected token: %s", string(s[i]))
  93. case parseAllColumnsState_State_End:
  94. break
  95. }
  96. }
  97. if state != parseAllColumnsState_State_End {
  98. return nil, errors.New("unexpected end")
  99. }
  100. return columns, nil
  101. }
  102. func isSpace(r rune) bool {
  103. return r == ' ' || r == '\t'
  104. }
  105. func isQuote(r rune) bool {
  106. return r == '`' || r == '"' || r == '\''
  107. }
  108. func isSeparator(r rune) bool {
  109. return r == ','
  110. }