github.com/dolthub/go-mysql-server@v0.18.0/enginetest/queries/column_alias_queries.go (about) 1 // Copyright 2022 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 queries 16 17 import ( 18 "github.com/dolthub/vitess/go/sqltypes" 19 20 "github.com/dolthub/go-mysql-server/sql/types" 21 22 "github.com/dolthub/go-mysql-server/sql" 23 ) 24 25 var ColumnAliasQueries = []ScriptTest{ 26 { 27 Name: "column aliases in a single scope", 28 SetUpScript: []string{ 29 "create table xy (x int primary key, y int);", 30 "create table uv (u int primary key, v int);", 31 "create table wz (w int, z int);", 32 "insert into xy values (0,0),(1,1),(2,2),(3,3);", 33 "insert into uv values (0,3),(3,0),(2,1),(1,2);", 34 "insert into wz values (0, 0), (1, 0), (1, 2)", 35 }, 36 Assertions: []ScriptTestAssertion{ 37 { 38 // Projections can create expression aliases 39 Query: `SELECT i AS cOl FROM mytable`, 40 ExpectedColumns: sql.Schema{ 41 { 42 Name: "cOl", 43 Type: types.Int64, 44 }, 45 }, 46 Expected: []sql.Row{{int64(1)}, {int64(2)}, {int64(3)}}, 47 }, 48 { 49 Query: `SELECT i AS cOl, s as COL FROM mytable`, 50 ExpectedColumns: sql.Schema{ 51 { 52 Name: "cOl", 53 Type: types.Int64, 54 }, 55 { 56 Name: "COL", 57 Type: types.MustCreateStringWithDefaults(sqltypes.VarChar, 20), 58 }, 59 }, 60 Expected: []sql.Row{{int64(1), "first row"}, {int64(2), "second row"}, {int64(3), "third row"}}, 61 }, 62 { 63 // Projection expressions may NOT reference aliases defined in projection expressions 64 // in the same scope 65 Query: `SELECT i AS new1, new1 as new2 FROM mytable`, 66 ExpectedErr: sql.ErrMisusedAlias, 67 }, 68 { 69 // The SQL standard disallows aliases in the same scope from being used in filter conditions 70 Query: `SELECT i AS cOl, s as COL FROM mytable where cOl = 1`, 71 ExpectedErr: sql.ErrColumnNotFound, 72 }, 73 { 74 // Alias expressions may NOT be used in from clauses 75 Query: "select t1.i as a, t1.s as b from mytable as t1 left join mytable as t2 on a = t2.i;", 76 ExpectedErr: sql.ErrColumnNotFound, 77 }, 78 { 79 // OrderBy clause may reference expression aliases at current scope 80 Query: "select 1 as a order by a desc;", 81 Expected: []sql.Row{{1}}, 82 }, 83 { 84 // If there is ambiguity between one table column and one alias, the alias gets precedence in the order 85 // by clause. (This is different from subqueries in projection expressions.) 86 Query: "select v as u from uv order by u;", 87 Expected: []sql.Row{{0}, {1}, {2}, {3}}, 88 }, 89 { 90 // If there is ambiguity between multiple aliases in an order by clause, it is an error 91 Query: "select u as u, v as u from uv order by u;", 92 ExpectedErr: sql.ErrAmbiguousColumnOrAliasName, 93 }, 94 { 95 // If there is ambiguity between one selected table column and one alias, the table column gets 96 // precedence in the group by clause. 97 Query: "select w, min(z) as w, max(z) as w from wz group by w;", 98 Expected: []sql.Row{{0, 0, 0}, {1, 0, 2}}, 99 }, 100 { 101 // GroupBy may use a column that is selected multiple times. 102 Query: "select w, w from wz group by w;", 103 Expected: []sql.Row{{0, 0}, {1, 1}}, 104 }, 105 { 106 // GroupBy may use expression aliases in grouping expressions 107 Query: `SELECT s as COL1, SUM(i) COL2 FROM mytable group by col1 order by col2`, 108 ExpectedColumns: sql.Schema{ 109 { 110 Name: "COL1", 111 Type: types.MustCreateStringWithDefaults(sqltypes.VarChar, 20), 112 }, 113 { 114 Name: "COL2", 115 Type: types.Float64, 116 }, 117 }, 118 Expected: []sql.Row{ 119 {"first row", float64(1)}, 120 {"second row", float64(2)}, 121 {"third row", float64(3)}, 122 }, 123 }, 124 { 125 // Having clause may reference expression aliases current scope 126 Query: "select t1.u as a from uv as t1 having a > 0 order by a;", 127 Expected: []sql.Row{{1}, {2}, {3}}, 128 }, 129 { 130 // Having clause may reference expression aliases from current scope 131 Query: "select t1.u as a from uv as t1 having a = t1.u order by a;", 132 Expected: []sql.Row{{0}, {1}, {2}, {3}}, 133 }, 134 { 135 // Expression aliases work when implicitly referenced by ordinal position 136 Query: `SELECT s as coL1, SUM(i) coL2 FROM mytable group by 1 order by 2`, 137 ExpectedColumns: sql.Schema{ 138 { 139 Name: "coL1", 140 Type: types.MustCreateStringWithDefaults(sqltypes.VarChar, 20), 141 }, 142 { 143 Name: "coL2", 144 Type: types.Float64, 145 }, 146 }, 147 Expected: []sql.Row{ 148 {"first row", float64(1)}, 149 {"second row", float64(2)}, 150 {"third row", float64(3)}, 151 }, 152 }, 153 { 154 // Expression aliases work when implicitly referenced by ordinal position 155 Query: `SELECT s as Date, SUM(i) TimeStamp FROM mytable group by 1 order by 2`, 156 ExpectedColumns: sql.Schema{ 157 { 158 Name: "Date", 159 Type: types.MustCreateStringWithDefaults(sqltypes.VarChar, 20), 160 }, 161 { 162 Name: "TimeStamp", 163 Type: types.Float64, 164 }, 165 }, 166 Expected: []sql.Row{ 167 {"first row", float64(1)}, 168 {"second row", float64(2)}, 169 {"third row", float64(3)}, 170 }, 171 }, 172 { 173 Query: "select t1.i as a from mytable as t1 having a = t1.i;", 174 Expected: []sql.Row{{1}, {2}, {3}}, 175 }, 176 }, 177 }, 178 { 179 Name: "column aliases in two scopes", 180 SetUpScript: []string{ 181 "create table xy (x int primary key, y int);", 182 "create table uv (u int primary key, v int);", 183 "insert into xy values (0,0),(1,1),(2,2),(3,3);", 184 "insert into uv values (0,3),(3,0),(2,1),(1,2);", 185 }, 186 Assertions: []ScriptTestAssertion{ 187 { 188 Query: `select "foo" as dummy, (select dummy)`, 189 Expected: []sql.Row{{"foo", "foo"}}, 190 }, 191 { 192 // https://github.com/dolthub/dolt/issues/4344 193 Query: "select x as v, (select u from uv where v = y) as u from xy;", 194 Expected: []sql.Row{{0, 3}, {1, 2}, {2, 1}, {3, 0}}, 195 }, 196 { 197 // GMS currently returns {0, 0, 0} The second alias seems to get overwritten. 198 // https://github.com/dolthub/go-mysql-server/issues/1286 199 Skip: true, 200 201 // When multiple aliases are defined with the same name, a subquery prefers the first definition 202 Query: "select 0 as a, 1 as a, (SELECT x from xy where x = a);", 203 Expected: []sql.Row{{0, 1, 0}}, 204 }, 205 { 206 Query: "SELECT 1 as a, (select a) as a;", 207 Expected: []sql.Row{{1, 1}}, 208 }, 209 { 210 Query: "SELECT 1 as a, (select a) as b;", 211 Expected: []sql.Row{{1, 1}}, 212 }, 213 { 214 Query: "SELECT 1 as a, (select a) as b from dual;", 215 Expected: []sql.Row{{1, 1}}, 216 }, 217 { 218 Query: "SELECT 1 as a, (select a) as b from xy;", 219 Expected: []sql.Row{{1, 1}, {1, 1}, {1, 1}, {1, 1}}, 220 }, 221 { 222 Query: "select x, (select 1) as y from xy;", 223 Expected: []sql.Row{{0, 1}, {1, 1}, {2, 1}, {3, 1}}, 224 }, 225 { 226 Query: "SELECT 1 as a, (select a) from xy;", 227 Expected: []sql.Row{{1, 1}, {1, 1}, {1, 1}, {1, 1}}, 228 }, 229 }, 230 }, 231 { 232 Name: "column aliases in three scopes", 233 SetUpScript: []string{ 234 "create table xy (x int primary key, y int);", 235 "create table uv (u int primary key, v int);", 236 "insert into xy values (0,0),(1,1),(2,2),(3,3);", 237 "insert into uv values (0,3),(3,0),(2,1),(1,2);", 238 }, 239 Assertions: []ScriptTestAssertion{ 240 { 241 Query: "select x, (select 1) as y, (select (select y as q)) as z from (select * from xy) as xy;", 242 Expected: []sql.Row{{0, 1, 0}, {1, 1, 1}, {2, 1, 2}, {3, 1, 3}}, 243 }, 244 }, 245 }, 246 { 247 Name: "various broken alias queries", 248 Assertions: []ScriptTestAssertion{ 249 { 250 // The second query in the union subquery returns "x" instead of mytable.i 251 // https://github.com/dolthub/dolt/issues/4256 252 Skip: true, 253 Query: `SELECT *, (select i union select i) as a from mytable;`, 254 Expected: []sql.Row{{1, "first row", 1}, {2, "second row", 2}, {3, "third row", 3}}, 255 }, 256 { 257 // Fails with an unresolved *plan.Project node error 258 // The second Project in the union subquery doens't seem to get its alias reference resolved 259 Skip: true, 260 Query: `SELECT 1 as a, (select a union select a) as b;`, 261 Expected: []sql.Row{{1, 1}}, 262 }, 263 { 264 // GMS executes this query, but it is not valid because of the forward ref of alias b. 265 // GMS should return an error about an invalid forward-ref. 266 Skip: true, 267 Query: `select 1 as a, (select b), 0 as b;`, 268 ExpectedErr: sql.ErrColumnNotFound, 269 }, 270 { 271 // GMS returns "expression 'dt.two' doesn't appear in the group by expressions", but MySQL will execute 272 // this query. 273 Skip: true, 274 Query: "select 1 as a, one + 1 as mod1, dt.* from mytable as t1, (select 1, 2 from mytable) as dt (one, two) where dt.one > 0 group by one;", 275 // column names: a, mod1, one, two 276 Expected: []sql.Row{{1, 2, 1, 2}}, 277 }, 278 { 279 // GMS returns `ambiguous column or alias name "b"` on both cases of `group by b` and `group by 1` inside subquery, but MySQL executes. 280 Skip: true, 281 Query: "select 1 as b, (select b group by b order by b) order by 1;", 282 Expected: []sql.Row{{1, 1}}, 283 }, 284 }, 285 }, 286 }