github.com/dolthub/go-mysql-server@v0.18.0/enginetest/queries/order_by_group_by_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/go-mysql-server/sql" 19 "github.com/dolthub/go-mysql-server/sql/analyzer/analyzererrors" 20 ) 21 22 var OrderByGroupByScriptTests = []ScriptTest{ 23 { 24 Name: "Basic order by/group by cases", 25 SetUpScript: []string{ 26 "use mydb;", 27 "create table members (id bigint primary key, team text);", 28 "insert into members values (3,'red'), (4,'red'),(5,'orange'),(6,'orange'),(7,'orange'),(8,'purple');", 29 }, 30 Assertions: []ScriptTestAssertion{ 31 { 32 Query: "select team as f from members order by id, f", 33 Expected: []sql.Row{{"red"}, {"red"}, {"orange"}, {"orange"}, {"orange"}, {"purple"}}, 34 }, 35 { 36 Query: "SELECT team, COUNT(*) FROM members GROUP BY team ORDER BY 2", 37 Expected: []sql.Row{ 38 {"purple", int64(1)}, 39 {"red", int64(2)}, 40 {"orange", int64(3)}, 41 }, 42 }, 43 { 44 Query: "SELECT team, COUNT(*) FROM members GROUP BY 1 ORDER BY 2", 45 Expected: []sql.Row{ 46 {"purple", int64(1)}, 47 {"red", int64(2)}, 48 {"orange", int64(3)}, 49 }, 50 }, 51 { 52 Query: "SELECT team, COUNT(*) FROM members GROUP BY team ORDER BY columndoesnotexist", 53 ExpectedErr: sql.ErrColumnNotFound, 54 }, 55 { 56 Query: "SELECT DISTINCT BINARY t1.id as id FROM members AS t1 JOIN members AS t2 ON t1.id = t2.id WHERE t1.id > 0 ORDER BY BINARY t1.id", 57 Expected: []sql.Row{{[]uint8{0x33}}, {[]uint8{0x34}}, {[]uint8{0x35}}, {[]uint8{0x36}}, {[]uint8{0x37}}, {[]uint8{0x38}}}, 58 }, 59 { 60 Query: "SELECT DISTINCT BINARY t1.id as id FROM members AS t1 JOIN members AS t2 ON t1.id = t2.id WHERE t1.id > 0 ORDER BY t1.id", 61 Expected: []sql.Row{{[]uint8{0x33}}, {[]uint8{0x34}}, {[]uint8{0x35}}, {[]uint8{0x36}}, {[]uint8{0x37}}, {[]uint8{0x38}}}, 62 }, 63 { 64 Query: "SELECT DISTINCT t1.id as id FROM members AS t1 JOIN members AS t2 ON t1.id = t2.id WHERE t2.id > 0 ORDER BY t1.id", 65 Expected: []sql.Row{{3}, {4}, {5}, {6}, {7}, {8}}, 66 }, 67 { 68 // aliases from outer scopes can be used in a subquery's having clause. 69 // https://github.com/dolthub/dolt/issues/4723 70 Query: "SELECT id as alias1, (SELECT alias1+1 group by alias1 having alias1 > 0) FROM members where id < 6;", 71 Expected: []sql.Row{{3, 4}, {4, 5}, {5, 6}}, 72 }, 73 { 74 // columns from outer scopes can be used in a subquery's having clause. 75 // https://github.com/dolthub/dolt/issues/4723 76 Query: "SELECT id, (SELECT UPPER(team) having id > 3) as upper_team FROM members where id < 6;", 77 Expected: []sql.Row{{3, nil}, {4, "RED"}, {5, "ORANGE"}}, 78 }, 79 { 80 // When there is ambiguity between a reference in an outer scope and a reference in the current 81 // scope, the reference in the innermost scope will be used. 82 // https://github.com/dolthub/dolt/issues/4723 83 Query: "SELECT id, (SELECT -1 as id having id < 10) as upper_team FROM members where id < 6;", 84 Expected: []sql.Row{{3, -1}, {4, -1}, {5, -1}}, 85 }, 86 }, 87 }, 88 { 89 Name: "Group by BINARY: https://github.com/dolthub/dolt/issues/6179", 90 SetUpScript: []string{ 91 "create table t (s varchar(100));", 92 "insert into t values ('abc'), ('def');", 93 "create table t1 (b binary(3));", 94 "insert into t1 values ('abc'), ('abc'), ('def'), ('abc'), ('def');", 95 }, 96 Assertions: []ScriptTestAssertion{ 97 { 98 Query: "select binary s from t group by binary s order by binary s", 99 Expected: []sql.Row{ 100 {[]uint8("abc")}, 101 {[]uint8("def")}, 102 }, 103 }, 104 { 105 Query: "select count(b), b from t1 group by b order by b", 106 Expected: []sql.Row{ 107 {3, []uint8("abc")}, 108 {2, []uint8("def")}, 109 }, 110 }, 111 { 112 Query: "select binary s from t group by binary s order by s", 113 Expected: []sql.Row{ 114 {[]uint8("abc")}, 115 {[]uint8("def")}, 116 }, 117 }, 118 }, 119 }, 120 { 121 Name: "https://github.com/dolthub/dolt/issues/3016", 122 SetUpScript: []string{ 123 "CREATE TABLE `users` (`id` int NOT NULL AUTO_INCREMENT, `username` varchar(255) NOT NULL, PRIMARY KEY (`id`));", 124 "INSERT INTO `users` (`id`,`username`) VALUES (1,'u2');", 125 "INSERT INTO `users` (`id`,`username`) VALUES (2,'u3');", 126 "INSERT INTO `users` (`id`,`username`) VALUES (3,'u4');", 127 "CREATE TABLE `tweet` (`id` int NOT NULL AUTO_INCREMENT, `user_id` int NOT NULL, `content` text NOT NULL, `timestamp` bigint NOT NULL, PRIMARY KEY (`id`), KEY `tweet_user_id` (`user_id`));", 128 "INSERT INTO `tweet` (`id`,`user_id`,`content`,`timestamp`) VALUES (1,1,'meow',1647463727);", 129 "INSERT INTO `tweet` (`id`,`user_id`,`content`,`timestamp`) VALUES (2,1,'purr',1647463727);", 130 "INSERT INTO `tweet` (`id`,`user_id`,`content`,`timestamp`) VALUES (3,2,'hiss',1647463727);", 131 "INSERT INTO `tweet` (`id`,`user_id`,`content`,`timestamp`) VALUES (4,3,'woof',1647463727);", 132 }, 133 Assertions: []ScriptTestAssertion{ 134 { 135 Query: "SELECT t1.username, COUNT(t1.id) FROM ((SELECT t2.id, t2.content, t3.username FROM tweet AS t2 INNER JOIN users AS t3 ON (-t2.user_id = -t3.id) WHERE (t3.username = 'u3')) UNION (SELECT t4.id, t4.content, `t5`.`username` FROM `tweet` AS t4 INNER JOIN users AS t5 ON (-t4.user_id = -t5.id) WHERE (t5.username IN ('u2', 'u4')))) AS t1 GROUP BY `t1`.`username` ORDER BY 1,2 DESC;", 136 Expected: []sql.Row{{"u2", 2}, {"u3", 1}, {"u4", 1}}, 137 }, 138 { 139 Query: "SELECT t1.username, COUNT(t1.id) AS ct FROM ((SELECT t2.id, t2.content, t3.username FROM tweet AS t2 INNER JOIN users AS t3 ON (-t2.user_id = -t3.id) WHERE (t3.username = 'u3')) UNION (SELECT t4.id, t4.content, `t5`.`username` FROM `tweet` AS t4 INNER JOIN users AS t5 ON (-t4.user_id = -t5.id) WHERE (t5.username IN ('u2', 'u4')))) AS t1 GROUP BY `t1`.`username` ORDER BY 1,2 DESC;", 140 Expected: []sql.Row{{"u2", 2}, {"u3", 1}, {"u4", 1}}, 141 }, 142 { 143 Query: "SELECT COUNT(id) as ct, user_id as uid FROM tweet GROUP BY tweet.user_id ORDER BY COUNT(id), user_id;", 144 Expected: []sql.Row{{1, 2}, {1, 3}, {2, 1}}, 145 }, 146 { 147 Query: "SELECT COUNT(tweet.id) as ct, user_id as uid FROM tweet GROUP BY tweet.user_id ORDER BY COUNT(id), user_id;", 148 Expected: []sql.Row{{1, 2}, {1, 3}, {2, 1}}, 149 }, 150 { 151 Query: "SELECT COUNT(id) as ct, user_id as uid FROM tweet GROUP BY tweet.user_id ORDER BY COUNT(tweet.id), user_id;", 152 Expected: []sql.Row{{1, 2}, {1, 3}, {2, 1}}, 153 }, 154 { 155 Query: "SELECT COUNT(id) as ct, user_id as uid FROM tweet GROUP BY tweet.user_id HAVING COUNT(tweet.id) > 0 ORDER BY COUNT(tweet.id), user_id;", 156 Expected: []sql.Row{{1, 2}, {1, 3}, {2, 1}}, 157 }, 158 { 159 Query: "SELECT COUNT(id) as ct, user_id as uid FROM tweet WHERE tweet.id is NOT NULL GROUP BY tweet.user_id ORDER BY COUNT(tweet.id), user_id;", 160 Expected: []sql.Row{{1, 2}, {1, 3}, {2, 1}}, 161 }, 162 { 163 Query: "SELECT COUNT(id) as ct, user_id as uid FROM tweet WHERE tweet.id is NOT NULL GROUP BY tweet.user_id HAVING COUNT(tweet.id) > 0 ORDER BY COUNT(tweet.id), user_id;", 164 Expected: []sql.Row{{1, 2}, {1, 3}, {2, 1}}, 165 }, 166 { 167 Query: "SELECT COUNT(id) as ct, user_id as uid FROM tweet WHERE tweet.id is NOT NULL GROUP BY tweet.user_id HAVING COUNT(tweet.id) > 0 ORDER BY COUNT(tweet.id), user_id LIMIT 1;", 168 Expected: []sql.Row{{1, 2}}, 169 }, 170 }, 171 }, 172 { 173 Name: "Group by with decimal columns", 174 Assertions: []ScriptTestAssertion{ 175 { 176 Query: "SELECT column_0, sum(column_1) FROM (values row(1.00,1), row(1.00,3), row(2,2), row(2,5), row(3,9)) a group by 1 order by 1;", 177 Expected: []sql.Row{{"1.00", float64(4)}, {"2.00", float64(7)}, {"3.00", float64(9)}}, 178 }, 179 }, 180 }, 181 { 182 // https://github.com/dolthub/dolt/issues/4739 183 Name: "Validation for use of non-aggregated columns with implicit grouping of all rows", 184 SetUpScript: []string{ 185 "CREATE TABLE t (num INTEGER, val DOUBLE);", 186 "INSERT INTO t VALUES (1, 0.01), (2,0.5);", 187 }, 188 Assertions: []ScriptTestAssertion{ 189 { 190 Query: "SELECT AVG(val), LAST_VALUE(val) OVER w FROM t WINDOW w AS (ORDER BY num RANGE BETWEEN UNBOUNDED PRECEDING AND UNBOUNDED FOLLOWING);", 191 ExpectedErr: sql.ErrNonAggregatedColumnWithoutGroupBy, 192 }, 193 { 194 Query: "SELECT 1 + AVG(val) + 1, LAST_VALUE(val) OVER w FROM t WINDOW w AS (ORDER BY num RANGE BETWEEN UNBOUNDED PRECEDING AND UNBOUNDED FOLLOWING);", 195 ExpectedErr: sql.ErrNonAggregatedColumnWithoutGroupBy, 196 }, 197 { 198 Query: "SELECT AVG(1), 1 + LAST_VALUE(val) OVER w FROM t WINDOW w AS (ORDER BY num RANGE BETWEEN UNBOUNDED PRECEDING AND UNBOUNDED FOLLOWING);", 199 ExpectedErr: sql.ErrNonAggregatedColumnWithoutGroupBy, 200 }, 201 { 202 // GMS currently allows this query to execute and chooses the first result for val. 203 // To match MySQL's behavior, GMS should be throwing an ErrNonAggregatedColumnWithoutGroupBy error. 204 Skip: true, 205 Query: "select AVG(val), val from t;", 206 ExpectedErr: sql.ErrNonAggregatedColumnWithoutGroupBy, 207 }, 208 { 209 // Test validation for a derived table opaque node 210 Query: "select * from (SELECT AVG(val), LAST_VALUE(val) OVER w FROM t WINDOW w AS (ORDER BY num RANGE BETWEEN UNBOUNDED PRECEDING AND UNBOUNDED FOLLOWING)) as dt;", 211 ExpectedErr: sql.ErrNonAggregatedColumnWithoutGroupBy, 212 }, 213 { 214 // Test validation for a union opaque node 215 Query: "select 1, 1 union SELECT AVG(val), LAST_VALUE(val) OVER w FROM t WINDOW w AS (ORDER BY num RANGE BETWEEN UNBOUNDED PRECEDING AND UNBOUNDED FOLLOWING);", 216 ExpectedErr: sql.ErrNonAggregatedColumnWithoutGroupBy, 217 }, 218 { 219 // Test validation for a recursive CTE opaque node 220 Query: "select * from (with recursive a as (select 1 as c1, 1 as c2 union SELECT AVG(t.val), LAST_VALUE(t.val) OVER w FROM t WINDOW w AS (ORDER BY num RANGE BETWEEN UNBOUNDED PRECEDING AND UNBOUNDED FOLLOWING)) select * from a union select * from a limit 1) as dt;", 221 ExpectedErr: sql.ErrNonAggregatedColumnWithoutGroupBy, 222 }, 223 }, 224 }, 225 { 226 Name: "group by with any_value()", 227 SetUpScript: []string{ 228 "use mydb;", 229 "create table members (id bigint primary key, team text);", 230 "insert into members values (3,'red'), (4,'red'),(5,'orange'),(6,'orange'),(7,'orange'),(8,'purple');", 231 }, 232 Assertions: []ScriptTestAssertion{ 233 { 234 Query: "select @@global.sql_mode", 235 Expected: []sql.Row{ 236 {"NO_ENGINE_SUBSTITUTION,ONLY_FULL_GROUP_BY,STRICT_TRANS_TABLES"}, 237 }, 238 }, 239 { 240 Query: "select @@session.sql_mode", 241 Expected: []sql.Row{ 242 {"NO_ENGINE_SUBSTITUTION,ONLY_FULL_GROUP_BY,STRICT_TRANS_TABLES"}, 243 }, 244 }, 245 { 246 Query: "select any_value(id), any_value(team) from members order by id", 247 Expected: []sql.Row{ 248 {3, "red"}, 249 {4, "red"}, 250 {5, "orange"}, 251 {6, "orange"}, 252 {7, "orange"}, 253 {8, "purple"}, 254 }, 255 }, 256 }, 257 }, 258 { 259 Name: "group by with strict errors", 260 SetUpScript: []string{ 261 "use mydb;", 262 "create table members (id bigint primary key, team text);", 263 "insert into members values (3,'red'), (4,'red'),(5,'orange'),(6,'orange'),(7,'orange'),(8,'purple');", 264 }, 265 Assertions: []ScriptTestAssertion{ 266 { 267 Query: "select @@global.sql_mode", 268 Expected: []sql.Row{ 269 {"NO_ENGINE_SUBSTITUTION,ONLY_FULL_GROUP_BY,STRICT_TRANS_TABLES"}, 270 }, 271 }, 272 { 273 Query: "select @@session.sql_mode", 274 Expected: []sql.Row{ 275 {"NO_ENGINE_SUBSTITUTION,ONLY_FULL_GROUP_BY,STRICT_TRANS_TABLES"}, 276 }, 277 }, 278 { 279 Query: "select id, team from members group by team", 280 ExpectedErr: analyzererrors.ErrValidationGroupBy, 281 }, 282 }, 283 }, 284 { 285 Name: "Group by null handling", 286 // https://github.com/dolthub/go-mysql-server/issues/1503 287 SetUpScript: []string{ 288 "create table t (pk int primary key, c1 varchar(10));", 289 "insert into t values (1, 'foo'), (2, 'foo'), (3, NULL);", 290 }, 291 Assertions: []ScriptTestAssertion{ 292 { 293 Query: "select c1, count(pk) from t group by c1;", 294 Expected: []sql.Row{ 295 {"foo", 2}, 296 {nil, 1}, 297 }, 298 }, 299 { 300 Query: "select c1, count(c1) from t group by c1;", 301 Expected: []sql.Row{ 302 {"foo", 2}, 303 {nil, 0}, 304 }, 305 }, 306 }, 307 }, 308 }