github.com/supabase/cli@v1.168.1/internal/utils/parser/state_test.go (about) 1 package parser 2 3 import ( 4 "strings" 5 "testing" 6 7 "github.com/stretchr/testify/assert" 8 "github.com/stretchr/testify/require" 9 ) 10 11 func checkSplit(t *testing.T, sql []string) { 12 input := strings.Join(sql, "") 13 output, err := Split(strings.NewReader(input)) 14 require.NoError(t, err) 15 assert.ElementsMatch(t, sql, output) 16 } 17 18 func TestLineComment(t *testing.T) { 19 t.Run("after separator", func(t *testing.T) { 20 sql := []string{"END;", "-- comment"} 21 checkSplit(t, sql) 22 }) 23 24 t.Run("before separator", func(t *testing.T) { 25 sql := []string{"SELECT --; 1"} 26 checkSplit(t, sql) 27 }) 28 29 t.Run("not started", func(t *testing.T) { 30 sql := []string{"- ;", "END"} 31 checkSplit(t, sql) 32 }) 33 34 t.Run("between lines", func(t *testing.T) { 35 sql := []string{"-- /* \n;", " */ END"} 36 checkSplit(t, sql) 37 }) 38 } 39 40 func TestBlockComment(t *testing.T) { 41 t.Run("contains separator", func(t *testing.T) { 42 sql := []string{"SELECT /* ; */ 1;"} 43 checkSplit(t, sql) 44 }) 45 46 t.Run("nested block", func(t *testing.T) { 47 sql := []string{"SELECT /*; /*;*/ ;*/ 1"} 48 checkSplit(t, sql) 49 }) 50 51 t.Run("not started", func(t *testing.T) { 52 sql := []string{"/ * ;", " */ END"} 53 checkSplit(t, sql) 54 }) 55 } 56 57 func TestSeparator(t *testing.T) { 58 t.Run("no spaces", func(t *testing.T) { 59 sql := []string{";", "END;", ";"} 60 checkSplit(t, sql) 61 }) 62 63 t.Run("between spaces", func(t *testing.T) { 64 sql := []string{"BEGIN ;", " END"} 65 checkSplit(t, sql) 66 }) 67 68 t.Run("backslash escaped", func(t *testing.T) { 69 sql := []string{"\\;;", "\\;"} 70 checkSplit(t, sql) 71 }) 72 } 73 74 func TestDollarQuote(t *testing.T) { 75 t.Run("named tag", func(t *testing.T) { 76 sql := []string{"$tag$ any ; string$tag$"} 77 checkSplit(t, sql) 78 }) 79 80 t.Run("anonymous tag", func(t *testing.T) { 81 sql := []string{"$$\"Dane's horse\"$$"} 82 checkSplit(t, sql) 83 }) 84 85 t.Run("not started", func(t *testing.T) { 86 sql := []string{"SELECT \"$\";", " $$"} 87 checkSplit(t, sql) 88 }) 89 } 90 91 func TestSingleQuote(t *testing.T) { 92 t.Run("escapes separator", func(t *testing.T) { 93 sql := []string{"SELECT ';' 1"} 94 checkSplit(t, sql) 95 }) 96 97 t.Run("preserves single quote", func(t *testing.T) { 98 sql := []string{"SELECT ';'';' 1"} 99 checkSplit(t, sql) 100 }) 101 102 t.Run("literal backslash", func(t *testing.T) { 103 sql := []string{"SELECT '\\';", " 1'"} 104 checkSplit(t, sql) 105 }) 106 } 107 108 func TestDoubleQuote(t *testing.T) { 109 t.Run("escapes separator", func(t *testing.T) { 110 sql := []string{`CREATE POLICY "cats;dogs" on cats_dogs;`, " END"} 111 checkSplit(t, sql) 112 }) 113 114 t.Run("preserves single quote", func(t *testing.T) { 115 sql := []string{`CREATE POLICY "cat's and dog's" on cats_dogs;`, " END"} 116 checkSplit(t, sql) 117 }) 118 119 t.Run("preserves double quote", func(t *testing.T) { 120 sql := []string{`CREATE POLICY "pet""name" on pets;`, " END"} 121 checkSplit(t, sql) 122 }) 123 } 124 125 func TestParentheses(t *testing.T) { 126 t.Run("preserves parentheses", func(t *testing.T) { 127 sql := []string{ 128 `CREATE RULE notify_me AS ON UPDATE TO mytable DO (NOTIFY mytable; SELECT "1");`, 129 `SELECT 1`, 130 } 131 checkSplit(t, sql) 132 }) 133 134 t.Run("ignores literals", func(t *testing.T) { 135 sql := []string{`CREATE RULE notify_me AS ON UPDATE TO mytable DO (-- ) 136 SELECT ')'; 137 -- ) 138 ) 139 `} 140 checkSplit(t, sql) 141 }) 142 } 143 144 func TestBeginAtomic(t *testing.T) { 145 t.Run("inline body", func(t *testing.T) { 146 sql := []string{`CREATE FUNCTION add(a integer, b integer) RETURNS integer 147 LANGUAGE SQL 148 IMMUTABLE STRICT PARALLEL SAFE 149 RETURNS NULL ON NULL INPUT 150 BEGIN ATOMIC 151 SELECT 'add'; 152 SELECT a + b; 153 END;`} 154 checkSplit(t, sql) 155 }) 156 157 t.Run("case insenstive", func(t *testing.T) { 158 sql := []string{"begin atomic; select 'end'; end"} 159 checkSplit(t, sql) 160 }) 161 162 t.Run("ignores literals", func(t *testing.T) { 163 sql := []string{`CREATE FUNCTION test() BEGIN 164 ATOMIC-- END; 165 -- END; 166 END 167 ;`} 168 checkSplit(t, sql) 169 }) 170 }