2
0

sql_matching.go 2.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116
  1. package pgserver
  2. import (
  3. "strings"
  4. "github.com/danfragoso/pizzasql-next/pkg/lexer"
  5. )
  6. func nextSQLToken(l *lexer.Lexer) lexer.Token {
  7. for {
  8. token := l.NextToken()
  9. if token.Type != lexer.TokenComment {
  10. return token
  11. }
  12. }
  13. }
  14. // Match complete token sequences, never substrings inside literals/comments or
  15. // projections that happen to mention a driver initialization query.
  16. func systemQueryKind(sql string) string {
  17. l := lexer.New(sql)
  18. first := nextSQLToken(l)
  19. if first.Type != lexer.TokenSELECT && !(first.Type == lexer.TokenIdent && strings.EqualFold(first.Literal, "SHOW")) {
  20. return ""
  21. }
  22. tokens := []string{strings.ToUpper(first.Literal)}
  23. for len(tokens) <= 4 {
  24. token := nextSQLToken(l)
  25. if token.Type == lexer.TokenSemicolon {
  26. if nextSQLToken(l).Type != lexer.TokenEOF {
  27. return ""
  28. }
  29. break
  30. }
  31. if token.Type == lexer.TokenEOF {
  32. break
  33. }
  34. if token.Type == lexer.TokenString || token.Type == lexer.TokenBlob || token.Type == lexer.TokenError {
  35. return ""
  36. }
  37. tokens = append(tokens, strings.ToUpper(token.Literal))
  38. }
  39. switch strings.Join(tokens, " ") {
  40. case "SELECT VERSION ( )":
  41. return "version"
  42. case "SELECT CURRENT_USER":
  43. return "current_user"
  44. case "SHOW SERVER_VERSION":
  45. return "server_version"
  46. case "SHOW SERVER_ENCODING":
  47. return "server_encoding"
  48. case "SHOW CLIENT_ENCODING":
  49. return "client_encoding"
  50. default:
  51. return ""
  52. }
  53. }
  54. func isSingleStatementSQL(sql string) bool {
  55. l := lexer.New(sql)
  56. ended := false
  57. for {
  58. token := nextSQLToken(l)
  59. if token.Type == lexer.TokenEOF {
  60. return true
  61. }
  62. if token.Type == lexer.TokenSemicolon {
  63. ended = true
  64. continue
  65. }
  66. if ended {
  67. return false
  68. }
  69. }
  70. }
  71. func catalogSource(sql string) string {
  72. l := lexer.New(sql)
  73. if nextSQLToken(l).Type != lexer.TokenSELECT {
  74. return ""
  75. }
  76. depth := 0
  77. for {
  78. token := nextSQLToken(l)
  79. switch token.Type {
  80. case lexer.TokenEOF, lexer.TokenError:
  81. return ""
  82. case lexer.TokenLParen:
  83. depth++
  84. case lexer.TokenRParen:
  85. depth--
  86. case lexer.TokenFROM:
  87. if depth != 0 {
  88. continue
  89. }
  90. name := nextSQLToken(l)
  91. if name.Type != lexer.TokenIdent {
  92. return ""
  93. }
  94. source := strings.ToUpper(name.Literal)
  95. if nextSQLToken(l).Type == lexer.TokenDot {
  96. name = nextSQLToken(l)
  97. if name.Type != lexer.TokenIdent {
  98. return ""
  99. }
  100. source += "." + strings.ToUpper(name.Literal)
  101. }
  102. switch source {
  103. case "INFORMATION_SCHEMA.TABLES", "INFORMATION_SCHEMA.COLUMNS", "INFORMATION_SCHEMA.TABLE_CONSTRAINTS", "INFORMATION_SCHEMA.KEY_COLUMN_USAGE", "PG_TABLES", "PG_INDEXES":
  104. return source
  105. default:
  106. return ""
  107. }
  108. }
  109. }
  110. }