github.com/dolthub/go-mysql-server@v0.18.0/sql/rowexec/create_view_test.go (about) 1 // Copyright 2020-2021 Dolthub, Inc. 2 // 3 // Licensed under the Apache License, Version 2.0 (the "License"); 4 // you may not use this file except in compliance with the License. 5 // You may obtain a copy of the License at 6 // 7 // http://www.apache.org/licenses/LICENSE-2.0 8 // 9 // Unless required by applicable law or agreed to in writing, software 10 // distributed under the License is distributed on an "AS IS" BASIS, 11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 // See the License for the specific language governing permissions and 13 // limitations under the License. 14 15 package rowexec 16 17 import ( 18 "context" 19 "testing" 20 21 "github.com/stretchr/testify/require" 22 23 "github.com/dolthub/go-mysql-server/memory" 24 "github.com/dolthub/go-mysql-server/sql" 25 "github.com/dolthub/go-mysql-server/sql/expression" 26 "github.com/dolthub/go-mysql-server/sql/plan" 27 "github.com/dolthub/go-mysql-server/sql/types" 28 ) 29 30 func newCreateView(db memory.MemoryDatabase, isReplace bool) *plan.CreateView { 31 table := memory.NewTable(db.Database(), "mytable", sql.NewPrimaryKeySchema(sql.Schema{ 32 {Name: "i", Source: "mytable", Type: types.Int32}, 33 {Name: "s", Source: "mytable", Type: types.Text}, 34 }), nil) 35 36 db.AddTable("db", table) 37 38 subqueryAlias := plan.NewSubqueryAlias("myview", "select i from mytable", 39 plan.NewProject( 40 []sql.Expression{ 41 expression.NewGetFieldWithTable(1, 1, types.Int32, table.Name(), "", "i", true), 42 }, 43 plan.NewUnresolvedTable(table.Name(), ""), 44 ), 45 ) 46 47 createView := plan.NewCreateView(db, subqueryAlias.Name(), subqueryAlias, isReplace, "CREATE VIEW myview AS SELECT i FROM mytable", "", "", "") 48 49 return createView 50 } 51 52 // Tests that CreateView works as expected and that the view is registered in 53 // the catalog when RowIter is called 54 func TestCreateViewWithRegistry(t *testing.T) { 55 require := require.New(t) 56 57 createView := newCreateView(memory.NewViewlessDatabase("mydb"), false) 58 59 ctx := sql.NewContext(context.Background()) 60 _, err := DefaultBuilder.buildNodeExec(ctx, createView, nil) 61 require.NoError(err) 62 63 expectedView := sql.NewView(createView.Name, createView.Child, createView.Definition.TextDefinition, createView.CreateViewString) 64 actualView, ok := ctx.GetViewRegistry().View(createView.Database().Name(), createView.Name) 65 require.True(ok) 66 require.Equal(expectedView, actualView) 67 } 68 69 // Tests that CreateView RowIter returns an error when the view exists 70 func TestCreateExistingViewNative(t *testing.T) { 71 createView := newCreateView(memory.NewDatabase("mydb"), false) 72 73 ctx := sql.NewContext(context.Background()) 74 _, err := DefaultBuilder.buildNodeExec(ctx, createView, nil) 75 require.NoError(t, err) 76 77 ctx = sql.NewContext(context.Background()) 78 _, err = DefaultBuilder.buildNodeExec(ctx, createView, nil) 79 require.Error(t, err) 80 require.True(t, sql.ErrExistingView.Is(err)) 81 } 82 83 // Tests that CreateView RowIter succeeds when the view exists and the 84 // IsReplace flag is set to true 85 func TestReplaceExistingViewNative(t *testing.T) { 86 db := memory.NewDatabase("mydb") 87 createView := newCreateView(db, false) 88 89 ctx := sql.NewContext(context.Background()) 90 _, err := DefaultBuilder.buildNodeExec(ctx, createView, nil) 91 require.NoError(t, err) 92 93 expectedViewTextDef := createView.Definition.TextDefinition 94 view, ok, err := db.GetViewDefinition(ctx, createView.Name) 95 require.NoError(t, err) 96 require.True(t, ok) 97 require.Equal(t, expectedViewTextDef, view.TextDefinition) 98 99 // This is kind of nonsensical, but we just want to see if it gets stored correctly 100 subqueryAlias := plan.NewSubqueryAlias("myview", "select i + 1 from mytable", 101 plan.NewProject( 102 []sql.Expression{ 103 expression.NewArithmetic( 104 expression.NewGetFieldWithTable(1, 1, types.Int32, "", "mytable", "i", true), 105 expression.NewLiteral(1, types.Int8), 106 "+", 107 ), 108 }, 109 plan.NewUnresolvedTable("mytable", ""), 110 ), 111 ) 112 113 createView = plan.NewCreateView(db, subqueryAlias.Name(), subqueryAlias, true, "CREATE VIEW myview AS SELECT i + 1 FROM mytable", "", "", "") 114 _, err = DefaultBuilder.buildNodeExec(ctx, createView, nil) 115 require.NoError(t, err) 116 117 view, ok, err = db.GetViewDefinition(ctx, createView.Name) 118 require.NoError(t, err) 119 require.True(t, ok) 120 require.Equal(t, subqueryAlias.TextDefinition, view.TextDefinition) 121 } 122 123 // Tests that CreateView works as expected and that the view is registered in 124 // the catalog when RowIter is called 125 func TestCreateViewNative(t *testing.T) { 126 db := memory.NewDatabase("mydb") 127 createView := newCreateView(db, false) 128 129 ctx := sql.NewContext(context.Background()) 130 _, err := DefaultBuilder.buildNodeExec(ctx, createView, nil) 131 require.NoError(t, err) 132 133 actualView, ok, err := db.GetViewDefinition(ctx, createView.Name) 134 135 require.True(t, ok) 136 require.NoError(t, err) 137 require.Equal(t, createView.Definition.TextDefinition, actualView.TextDefinition) 138 } 139 140 // Tests that CreateView RowIter returns an error when the view exists 141 func TestCreateExistingViewWithRegistry(t *testing.T) { 142 require := require.New(t) 143 144 createView := newCreateView(memory.NewViewlessDatabase("mydb"), false) 145 146 view := createView.View() 147 viewReg := sql.NewViewRegistry() 148 err := viewReg.Register(createView.Database().Name(), view) 149 require.NoError(err) 150 151 sess := sql.NewBaseSession() 152 sess.SetViewRegistry(viewReg) 153 ctx := sql.NewContext(context.Background(), sql.WithSession(sess)) 154 _, err = DefaultBuilder.buildNodeExec(ctx, createView, nil) 155 require.Error(err) 156 require.True(sql.ErrExistingView.Is(err)) 157 } 158 159 // Tests that CreateView RowIter succeeds when the view exists and the 160 // IsReplace flag is set to true 161 func TestReplaceExistingViewWithRegistry(t *testing.T) { 162 require := require.New(t) 163 164 createView := newCreateView(memory.NewViewlessDatabase("mydb"), false) 165 166 view := sql.NewView(createView.Name, nil, "", "") 167 viewReg := sql.NewViewRegistry() 168 err := viewReg.Register(createView.Database().Name(), view) 169 require.NoError(err) 170 171 createView.IsReplace = true 172 173 sess := sql.NewBaseSession() 174 sess.SetViewRegistry(viewReg) 175 ctx := sql.NewContext(context.Background(), sql.WithSession(sess)) 176 _, err = DefaultBuilder.buildNodeExec(ctx, createView, nil) 177 require.NoError(err) 178 179 expectedView := createView.View() 180 actualView, ok := ctx.GetViewRegistry().View(createView.Database().Name(), createView.Name) 181 require.True(ok) 182 require.Equal(expectedView, actualView) 183 }