2
0

jsonb_test.go 2.7 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182
  1. package analyzer
  2. import (
  3. "testing"
  4. )
  5. // jsonbCatalog adds a table with a JSONB column to the shared test catalog.
  6. func jsonbCatalog() *Catalog {
  7. catalog := setupCatalog()
  8. catalog.CreateTable(&TableInfo{
  9. Name: "docs",
  10. Columns: []ColumnInfo{
  11. {Name: "id", Type: TypeInteger, PrimaryKey: true},
  12. {Name: "doc", Type: TypeJSONB, Nullable: true},
  13. {Name: "body", Type: TypeText, Nullable: true},
  14. },
  15. })
  16. return catalog
  17. }
  18. func TestTypeFromNameJSONB(t *testing.T) {
  19. if got := TypeFromName("JSONB"); got != TypeJSONB {
  20. t.Fatalf("TypeFromName(JSONB) = %v, want JSONB", got)
  21. }
  22. // JSON stays a text-backed alias and must not be promoted to native jsonb.
  23. if got := TypeFromName("JSON"); got == TypeJSONB {
  24. t.Fatal("TypeFromName(JSON) = JSONB, want the existing text-backed affinity")
  25. }
  26. if !TypeJSONB.IsComparable(TypeJSONB) || !TypeJSONB.IsComparable(TypeText) {
  27. t.Fatal("jsonb must compare with jsonb and text")
  28. }
  29. if TypeJSONB.IsComparable(TypeInteger) {
  30. t.Fatal("jsonb must not compare with an integer")
  31. }
  32. if got := CommonType(TypeJSONB, TypeText); got != TypeJSONB {
  33. t.Fatalf("CommonType(JSONB, TEXT) = %v, want JSONB", got)
  34. }
  35. }
  36. func TestAnalyzeJSONBExpressions(t *testing.T) {
  37. a := New(jsonbCatalog())
  38. for _, sql := range []string{
  39. `SELECT doc -> 'a', doc ->> 'a' FROM docs`,
  40. `SELECT doc #> '{a}', doc #>> '{a}', doc #- '{a}' FROM docs`,
  41. `SELECT doc @> '{}'::jsonb, doc <@ '{}'::jsonb FROM docs`,
  42. `SELECT doc ? 'a', doc ?| '{a}', doc ?& '{a}' FROM docs`,
  43. `SELECT doc || '{}'::jsonb, doc - 'a', doc - 1 FROM docs`,
  44. `SELECT '{}'::jsonb, CAST('{}' AS JSONB), to_jsonb(doc) FROM docs`,
  45. `SELECT jsonb_typeof(doc), jsonb_array_length(doc), jsonb_pretty(doc) FROM docs`,
  46. `SELECT jsonb_build_object('a', 1), jsonb_build_array(1, 'x') FROM docs`,
  47. `SELECT jsonb_set(doc, '{a}', '1'), jsonb_insert(doc, '{a}', '1') FROM docs`,
  48. `SELECT * FROM jsonb_each('{"a":1}')`,
  49. `SELECT value FROM jsonb_array_elements('[1]')`,
  50. `SELECT jsonb_object_keys FROM jsonb_object_keys('{"a":1}')`,
  51. `SELECT CASE WHEN id = 1 THEN doc ELSE '{}'::jsonb END FROM docs`,
  52. `SELECT COALESCE(doc, '{}'::jsonb) FROM docs`,
  53. } {
  54. if err := analyze(t, a, sql); err != nil {
  55. t.Errorf("%s: unexpected error: %v", sql, err)
  56. }
  57. }
  58. for _, sql := range []string{
  59. `SELECT doc = 5 FROM docs`,
  60. `SELECT doc + 1 FROM docs`,
  61. `SELECT 1 - doc FROM docs`,
  62. `SELECT doc & 1 FROM docs`,
  63. `SELECT doc || 1 FROM docs`,
  64. `SELECT doc - doc FROM docs`,
  65. `SELECT doc -> 'a' = 1 FROM docs`,
  66. `SELECT doc -> 'a' @> 1 FROM docs`,
  67. } {
  68. err := analyze(t, a, sql)
  69. if err == nil {
  70. t.Errorf("%s: expected a type error", sql)
  71. continue
  72. }
  73. if analysisErr, ok := err.(*AnalysisError); !ok || analysisErr.Type != ErrTypeMismatch {
  74. t.Errorf("%s: error = %v, want a type mismatch", sql, err)
  75. }
  76. }
  77. }