srf_alias_test.go 3.2 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677
  1. package pgserver
  2. import "testing"
  3. // PostgreSQL's `AS alias(col, ...)` list renames a set-returning function's
  4. // output columns in the projection and in WHERE.
  5. func TestSetReturningFunctionColumnAliases(t *testing.T) {
  6. c, conn := arrayConnection(t)
  7. conn.reset()
  8. messages := runSimple(t, c, conn, `SELECT unnest FROM unnest(ARRAY[1,2,3]) AS t(unnest)`)
  9. if errMsg := findError(messages); errMsg != nil {
  10. t.Fatalf("unnest alias list failed: %s", errorCode(errMsg))
  11. }
  12. columns := rowDescriptionColumns(t, findRowDescription(t, messages).Data)
  13. if len(columns) != 1 || columns[0] != "unnest" {
  14. t.Fatalf("unnest alias columns = %v, want [unnest]", columns)
  15. }
  16. if rows := countMessageType(messages, MsgDataRow); rows != 3 {
  17. t.Fatalf("unnest alias rows = %d, want 3", rows)
  18. }
  19. conn.reset()
  20. messages = runSimple(t, c, conn, `SELECT n FROM unnest(ARRAY[10,20,30]) AS t(n) WHERE n > 10 ORDER BY n`)
  21. if errMsg := findError(messages); errMsg != nil {
  22. t.Fatalf("unnest renamed column failed: %s", errorCode(errMsg))
  23. }
  24. if columns := rowDescriptionColumns(t, findRowDescription(t, messages).Data); len(columns) != 1 || columns[0] != "n" {
  25. t.Fatalf("unnest renamed columns = %v, want [n]", columns)
  26. }
  27. if row := firstDataRow(t, messages); len(row) != 1 || row[0] != "20" {
  28. t.Fatalf("unnest renamed first row = %v, want [20]", row)
  29. }
  30. conn.reset()
  31. messages = runSimple(t, c, conn, `SELECT k, v FROM jsonb_each('{"b":2,"a":1}') AS e(k, v) ORDER BY k`)
  32. if errMsg := findError(messages); errMsg != nil {
  33. t.Fatalf("jsonb_each renamed columns failed: %s", errorCode(errMsg))
  34. }
  35. if columns := rowDescriptionColumns(t, findRowDescription(t, messages).Data); len(columns) != 2 || columns[0] != "k" || columns[1] != "v" {
  36. t.Fatalf("jsonb_each renamed columns = %v, want [k v]", columns)
  37. }
  38. if row := firstDataRow(t, messages); len(row) != 2 || row[0] != "a" || row[1] != "1" {
  39. t.Fatalf("jsonb_each renamed first row = %v, want [a 1]", row)
  40. }
  41. // An alias without a column list keeps the default names.
  42. conn.reset()
  43. messages = runSimple(t, c, conn, `SELECT key, value FROM jsonb_each('{"a":1}') AS e`)
  44. if errMsg := findError(messages); errMsg != nil {
  45. t.Fatalf("alias-only jsonb_each failed: %s", errorCode(errMsg))
  46. }
  47. if columns := rowDescriptionColumns(t, findRowDescription(t, messages).Data); len(columns) != 2 || columns[0] != "key" || columns[1] != "value" {
  48. t.Fatalf("alias-only columns = %v, want [key value]", columns)
  49. }
  50. }
  51. // An alias list with the wrong arity reports invalid_column_reference (42P10).
  52. func TestSetReturningFunctionColumnAliasArity(t *testing.T) {
  53. c, conn := arrayConnection(t)
  54. for _, sql := range []string{
  55. `SELECT * FROM unnest(ARRAY[1]) AS t(a, b)`,
  56. `SELECT * FROM jsonb_each('{"a":1}') AS e(k)`,
  57. } {
  58. conn.reset()
  59. messages := runSimple(t, c, conn, sql)
  60. errMsg := findError(messages)
  61. if errMsg == nil || errorCode(errMsg) != ErrCodeInvalidColumnReference {
  62. t.Fatalf("%s error = %v, want 42P10", sql, messages)
  63. }
  64. }
  65. conn.reset()
  66. messages := runExtendedParseBindExecute(t, c, conn, `SELECT * FROM unnest($1) AS t(a, b)`, 1007, `{1}`)
  67. if errMsg := findError(messages); errMsg == nil || errorCode(errMsg) != ErrCodeInvalidColumnReference {
  68. t.Fatalf("extended alias arity error = %v, want 42P10", messages)
  69. }
  70. }