2
0

sql_matching_test.go 3.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108
  1. package pgserver
  2. import (
  3. "strings"
  4. "testing"
  5. )
  6. func TestBindQuerySkipsCommentsAndQuotedRegions(t *testing.T) {
  7. for _, tc := range []struct{ query, want string }{
  8. {"SELECT $1 /* ' $99 */ + $2", "SELECT 1 /* ' $99 */ + 2"},
  9. {"SELECT $1 -- '$99\n + $2", "SELECT 1 -- '$99\n + 2"},
  10. {"SELECT $1 -- $99", "SELECT 1 -- $99"},
  11. {"SELECT '$99''$88', \"$77\", `$66`, [$55], $1", "SELECT '$99''$88', \"$77\", `$66`, [$55], 1"},
  12. {"SELECT '$1 /* no comment */', $2", "SELECT '$1 /* no comment */', 2"},
  13. } {
  14. got, err := bindQuery(tc.query, []boundParameter{{value: []byte("1")}, {value: []byte("2")}})
  15. if err != nil || got != tc.want {
  16. t.Fatalf("%q: got %q err=%v want %q", tc.query, got, err, tc.want)
  17. }
  18. }
  19. if _, err := bindQuery("SELECT $99999999999999999999999999", nil); err == nil {
  20. t.Fatal("overflowed parameter number accepted")
  21. }
  22. }
  23. func TestCommentedPreparedQueryExecutesBothParameters(t *testing.T) {
  24. c, client := newDataConnection(t)
  25. c.statements[""] = &preparedStatement{query: "SELECT $1 /* ' $99 */ + $2", paramOIDs: []int32{20, 20}}
  26. bind := NewMessageBuilder()
  27. bind.WriteString("")
  28. bind.WriteString("")
  29. bind.WriteInt16(0)
  30. bind.WriteInt16(2)
  31. for _, value := range []string{"1", "2"} {
  32. bind.WriteInt32(int32(len(value)))
  33. bind.WriteBytes([]byte(value))
  34. }
  35. bind.WriteInt16(0)
  36. if err := c.handleBind(&Message{Type: MsgBind, Data: bind.Bytes()}); err != nil {
  37. t.Fatal(err)
  38. }
  39. portal := c.portals[""]
  40. if portal == nil {
  41. t.Fatal("Bind failed")
  42. }
  43. messages := runExtendedExecution(t, c, client, portal.query)
  44. found := false
  45. for _, message := range messages {
  46. if message.Type == MsgErrorResponse {
  47. t.Fatalf("bound execution failed: %s", errorCode(message))
  48. }
  49. if message.Type == MsgDataRow {
  50. values := dataRowValues(t, message)
  51. if len(values) != 1 || values[0] != "3" {
  52. t.Fatal(values)
  53. }
  54. found = true
  55. }
  56. }
  57. if !found {
  58. t.Fatal("no result row")
  59. }
  60. }
  61. func TestSystemQueryMatchingDoesNotInterceptLiteralsOrProjections(t *testing.T) {
  62. c, client := newDataConnection(t)
  63. for _, literal := range []string{"SELECT VERSION()", "SELECT CURRENT_USER", "SHOW SERVER_VERSION", "FROM PG_TABLES", "FROM INFORMATION_SCHEMA.TABLES"} {
  64. messages := runQuery(t, c, client, &Message{Type: MsgQuery, Data: []byte("SELECT '" + literal + "'\x00")})
  65. found := false
  66. for _, message := range messages {
  67. if message.Type == MsgErrorResponse {
  68. t.Fatalf("literal %q failed: %s", literal, errorCode(message))
  69. }
  70. if message.Type == MsgDataRow {
  71. values := dataRowValues(t, message)
  72. if len(values) != 1 || values[0] != literal {
  73. t.Fatalf("literal %q intercepted: %v", literal, values)
  74. }
  75. found = true
  76. }
  77. }
  78. if !found {
  79. t.Fatalf("literal %q produced no row", literal)
  80. }
  81. }
  82. for _, sql := range []string{"SELECT version() + 1", "SELECT current_user, 1", "SELECT 1 /* SELECT VERSION() */", "SHOW other_server_version"} {
  83. if kind := systemQueryKind(sql); kind != "" {
  84. t.Fatalf("%q intercepted as %s", sql, kind)
  85. }
  86. }
  87. for _, sql := range []string{"select version ( ) /* ; SELECT 2 */;", "-- initialization\nSELECT version()"} {
  88. messages := runQuery(t, c, client, &Message{Type: MsgQuery, Data: []byte(sql + "\x00")})
  89. if values := dataRowValues(t, messages[1]); !strings.Contains(values[0], "PizzaSQL") {
  90. t.Fatal(values)
  91. }
  92. }
  93. }
  94. func TestSingleStatementMatchingIgnoresCommentSemicolons(t *testing.T) {
  95. for _, sql := range []string{"SELECT ';'", "SELECT 1 /* ; ' */; -- ; SELECT 2", "SELECT 1; ;"} {
  96. if !isSingleStatementSQL(sql) {
  97. t.Fatalf("single statement rejected: %q", sql)
  98. }
  99. }
  100. if isSingleStatementSQL("SELECT 1; /* ; */ SELECT 2") {
  101. t.Fatal("batch accepted as one statement")
  102. }
  103. }