github.com/rohankumardubey/aresdb@v0.0.2-0.20190517170215-e54e3ca06b9c/query/sql_parser_test.go (about) 1 // Copyright (c) 2017-2018 Uber Technologies, 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 query 16 17 import ( 18 "github.com/onsi/ginkgo" 19 . "github.com/onsi/gomega" 20 "github.com/uber/aresdb/common" 21 ) 22 23 var _ = ginkgo.Describe("SQL Parser", func() { 24 25 logger := common.NewLoggerFactory().GetDefaultLogger() 26 27 runTest := func(sqls []string, aql AQLQuery, log common.Logger) { 28 for _, sql := range sqls { 29 actual, err := Parse(sql, logger) 30 expected := aql 31 expected.SQLQuery = sql 32 Ω(err).Should(BeNil()) 33 Ω(*actual).Should(BeEquivalentTo(expected)) 34 } 35 } 36 37 ginkgo.It("parse row filters should work", func() { 38 sqls := []string{ 39 `SELECT count(*) AS completed_trips, sum(fare) 40 FROM trips 41 WHERE status='completed' AND NOT status = 'cancelled' OR marketplace='agora' 42 GROUP BY status`, 43 } 44 res := AQLQuery{ 45 Table: "trips", 46 Measures: []Measure{{Alias: "completed_trips", Expr: "count(*)"}, {Expr: "sum(fare)"}}, 47 Filters: []string{"status='completed' AND NOT status = 'cancelled' OR marketplace='agora'"}, 48 Dimensions: []Dimension{{Expr: "status"}}, 49 } 50 runTest(sqls, res, logger) 51 }) 52 53 ginkgo.It("parse dimensions should work", func() { 54 sqls := []string{ 55 `SELECT status AS trip_status, count(*) 56 FROM trips 57 GROUP BY trip_status;`, 58 } 59 res := AQLQuery{ 60 Table: "trips", 61 Measures: []Measure{{Alias: "trip_status", Expr: "status"}, {Expr: "count(*)"}}, 62 Dimensions: []Dimension{{Alias: "trip_status", Expr: "status"}}, 63 } 64 runTest(sqls, res, logger) 65 }) 66 67 ginkgo.It("parse non agg AQLQuery should work", func() { 68 sqls := []string{ 69 `SELECT field1, * 70 FROM trips;`, 71 } 72 res := AQLQuery{ 73 Table: "trips", 74 Measures: []Measure{{Expr: "1"}}, 75 Dimensions: []Dimension{{Expr: "field1"}, {Expr: "*"}}, 76 } 77 runTest(sqls, res, logger) 78 }) 79 80 ginkgo.It("parse sort by should work", func() { 81 sqls := []string{ 82 `SELECT field1 83 FROM trips 84 ORDER BY field1;`, 85 } 86 res := AQLQuery{ 87 Table: "trips", 88 Measures: []Measure{{Expr: "1"}}, 89 Dimensions: []Dimension{{Expr: "field1"}}, 90 Sorts: []SortField{ 91 {Name: "field1", Order: "ASC"}, 92 }, 93 } 94 runTest(sqls, res, logger) 95 }) 96 97 ginkgo.It("parse time UDFs should work", func() { 98 99 sqls := []string{ 100 // Precision truncation based bucketizer. 101 `SELECT count(*) FROM trips 102 GROUP BY aql_time_bucket_minute("request_at", "minute", "America/New_York");`, 103 `SELECT count(*) FROM trips 104 GROUP BY aql_time_bucket_hour("request_at", "minute", "America/New_York");`, 105 `SELECT count(*) FROM trips 106 GROUP BY aql_time_bucket_day("request_at", "minute", "America/New_York");`, 107 `SELECT count(*) FROM trips 108 GROUP BY aql_time_bucket_week("request_at", "minute", "America/New_York");`, 109 `SELECT count(*) FROM trips 110 GROUP BY aql_time_bucket_month("request_at", "minute", "America/New_York");`, 111 `SELECT count(*) FROM trips 112 GROUP BY aql_time_bucket_quarter("request_at", "minute", "America/New_York");`, 113 `SELECT count(*) FROM trips 114 GROUP BY aql_time_bucket_year("request_at", "minute", "America/New_York");`, 115 // Component based bucketizer. 116 `SELECT count(*) FROM trips 117 GROUP BY aql_time_bucket_time_of_day("request_at", "minute", "America/New_York");`, 118 `SELECT count(*) FROM trips 119 GROUP BY aql_time_bucket_minutes_of_day("request_at", "minute", "America/New_York");`, 120 `SELECT count(*) FROM trips 121 GROUP BY aql_time_bucket_hour_of_day("request_at", "minute", "America/New_York");`, 122 `SELECT count(*) FROM trips 123 GROUP BY aql_time_bucket_hour_of_week("request_at", "minute", "America/New_York");`, 124 `SELECT count(*) FROM trips 125 GROUP BY aql_time_bucket_day_of_week("request_at", "minute", "America/New_York");`, 126 `SELECT count(*) FROM trips 127 GROUP BY aql_time_bucket_day_of_month("request_at", "minute", "America/New_York");`, 128 `SELECT count(*) FROM trips 129 GROUP BY aql_time_bucket_day_of_year("request_at", "minute", "America/New_York");`, 130 `SELECT count(*) FROM trips 131 GROUP BY aql_time_bucket_month_of_year("request_at", "minute", "America/New_York");`, 132 `SELECT count(*) FROM trips 133 GROUP BY aql_time_bucket_quarter_of_year("request_at", "minute", "America/New_York");`, 134 } 135 136 td := Dimension{Expr: "request_at", TimeUnit: "minute"} 137 tbs := []string{"minute", "hour", "day", "week", "month", "quarter", "year", 138 "time of day", "minutes of day", "hour of day", "hour of week", 139 "day of week", "day of month", "day of year", "month of year", "quarter of year"} 140 res := AQLQuery{ 141 Table: "trips", 142 Measures: []Measure{{Expr: "count(*)"}}, 143 Dimensions: make([]Dimension, 1), 144 Timezone: "America/New_York", 145 } 146 for i, sql := range sqls { 147 aql, err := Parse(sql, logger) 148 Ω(err).Should(BeNil()) 149 td.TimeBucketizer = tbs[i] 150 res.Dimensions[0] = td 151 res.SQLQuery = sql 152 Ω(*aql).Should(Equal(res)) 153 } 154 }) 155 156 ginkgo.It("parse time filters, time dimension and timezone should work", func() { 157 sqls := []string{ 158 `SELECT count(*) 159 FROM trips 160 161 WHERE aql_time_filter(request_at, "96 quarter-hours ago", "1 quarter-hours ago", America/New_York) 162 GROUP BY aql_time_bucket_minute(request_at, "minute", America/New_York);`, 163 } 164 res := AQLQuery{ 165 Table: "trips", 166 Measures: []Measure{{Expr: "count(*)"}}, 167 TimeFilter: TimeFilter{Column: "request_at", From: "96 quarter-hours ago", To: "1 quarter-hours ago"}, 168 Dimensions: []Dimension{{Expr: "request_at", TimeBucketizer: "minute", TimeUnit: "minute"}}, 169 Timezone: "America/New_York", 170 } 171 runTest(sqls, res, logger) 172 }) 173 174 ginkgo.It("parse time filters, time dimension and timezone and row filters should work", func() { 175 sqls := []string{ 176 `SELECT count(*) 177 FROM trips 178 WHERE aql_time_filter(request_at, "96 quarter-hours ago", "1 quarter-hours ago", America/New_York) AND marketplace="agora" 179 GROUP BY aql_time_bucket_minutes(request_at, "minute", America/New_York);`, 180 } 181 res := AQLQuery{ 182 Table: "trips", 183 Measures: []Measure{{Expr: "count(*)"}}, 184 TimeFilter: TimeFilter{Column: "request_at", From: "96 quarter-hours ago", To: "1 quarter-hours ago"}, 185 Dimensions: []Dimension{{Expr: "request_at", TimeBucketizer: "minutes", TimeUnit: "minute"}}, 186 Filters: []string{`marketplace="agora"`}, 187 Timezone: "America/New_York", 188 } 189 runTest(sqls, res, logger) 190 }) 191 192 ginkgo.It("parse numeric bucketizer should work", func() { 193 sqls := []string{ 194 `SELECT population AS pop, count(*) 195 FROM trips 196 WHERE aql_time_filter(request_at, "96 quarter-hours ago", "1 quarter-hours ago", America/New_York) AND marketplace="agora" 197 GROUP BY aql_time_bucket_hour(request_at, "minute", America/New_York), aql_numeric_bucket_logbase(pop, 2);`, 198 } 199 res := AQLQuery{ 200 Table: "trips", 201 Measures: []Measure{{Alias: "pop", Expr: "population"}, {Expr: "count(*)"}}, 202 Dimensions: []Dimension{{Expr: "request_at", TimeBucketizer: "hour", TimeUnit: "minute"}, {Expr: "pop", NumericBucketizer: NumericBucketizerDef{LogBase: 2}}}, 203 TimeFilter: TimeFilter{Column: "request_at", From: "96 quarter-hours ago", To: "1 quarter-hours ago"}, 204 Filters: []string{`marketplace="agora"`}, 205 Timezone: "America/New_York", 206 } 207 runTest(sqls, res, logger) 208 }) 209 210 ginkgo.It("parse join should work", func() { 211 sqls := []string{ 212 `SELECT population AS pop, count(*) 213 FROM trips 214 LEFT JOIN trips AS rush_leg 215 ON trips.workflow_uuid=rush_leg.workflow_uuid AND status='completed' 216 LEFT JOIN api_cities AS cities 217 ON cities.id=city_id 218 WHERE aql_time_filter(request_at, "96 quarter-hours ago", "1 quarter-hours ago", America/New_York) AND marketplace="agora" 219 GROUP BY aql_time_bucket_hours(request_at, "minute", America/New_York), aql_numeric_bucket_logbase(pop, 2);`, 220 } 221 res := AQLQuery{ 222 Table: "trips", 223 Joins: []Join{ 224 {Table: "trips", Alias: "rush_leg", Conditions: []string{"trips.workflow_uuid=rush_leg.workflow_uuid", "status='completed'"}}, 225 {Table: "api_cities", Alias: "cities", Conditions: []string{"cities.id=city_id"}}, 226 }, 227 Measures: []Measure{{Alias: "pop", Expr: "population"}, {Expr: "count(*)"}}, 228 Dimensions: []Dimension{{Expr: "request_at", TimeBucketizer: "hours", TimeUnit: "minute"}, {Expr: "pop", NumericBucketizer: NumericBucketizerDef{LogBase: 2}}}, 229 TimeFilter: TimeFilter{Column: "request_at", From: "96 quarter-hours ago", To: "1 quarter-hours ago"}, 230 Filters: []string{`marketplace="agora"`}, 231 Timezone: "America/New_York", 232 } 233 runTest(sqls, res, logger) 234 }) 235 236 ginkgo.It("parse composite measures should work", func() { 237 sqls := []string{ 238 // test SubQuery 239 `SELECT Completed, Requested, Completed/Requested 240 FROM 241 (SELECT count(*) AS Requested 242 FROM trips 243 LEFT JOIN trips AS rush_leg 244 ON trips.workflow_uuid=rush_leg.workflow_uuid AND status='completed' 245 LEFT JOIN api_cities AS cities 246 ON cities.id=city_id 247 WHERE aql_time_filter(request_at, "96 quarter-hours ago", "1 quarter-hours ago", America/New_York) AND marketplace="agora" 248 GROUP BY aql_time_bucket_day(request_at, "minute", America/New_York), aql_numeric_bucket_logbase(pop, 2)) AS m1 249 NATURAL LEFT JOIN 250 (SELECT count(*) AS Completed 251 FROM trips 252 LEFT JOIN trips AS rush_leg 253 ON trips.workflow_uuid=rush_leg.workflow_uuid AND status='completed' 254 LEFT JOIN api_cities AS cities 255 ON cities.id=city_id 256 WHERE aql_time_filter(request_at, "96 quarter-hours ago", "1 quarter-hours ago", America/New_York) AND marketplace="agora" AND status='completed' 257 GROUP BY aql_time_bucket_day(request_at, "minute", America/New_York), aql_numeric_bucket_logbase(pop, 2)) AS m2;`, 258 // test WithQuery 259 `WITH m1 (Requested) AS (SELECT count(*) AS Requested 260 FROM trips 261 LEFT JOIN trips AS rush_leg 262 ON trips.workflow_uuid=rush_leg.workflow_uuid AND status='completed' 263 LEFT JOIN api_cities AS cities 264 ON cities.id=city_id 265 WHERE aql_time_filter(request_at, "96 quarter-hours ago", "1 quarter-hours ago", America/New_York) AND marketplace="agora" 266 GROUP BY aql_time_bucket_day(request_at, "minute", America/New_York), aql_numeric_bucket_logbase(pop, 2)), 267 m2 (Completed) AS 268 (SELECT count(*) AS Completed 269 FROM trips 270 LEFT JOIN trips AS rush_leg 271 ON trips.workflow_uuid=rush_leg.workflow_uuid AND status='completed' 272 LEFT JOIN api_cities AS cities 273 ON cities.id=city_id 274 WHERE aql_time_filter(request_at, "96 quarter-hours ago", "1 quarter-hours ago", America/New_York) AND marketplace="agora" AND status='completed' 275 GROUP BY aql_time_bucket_day(request_at, "minute", America/New_York), aql_numeric_bucket_logbase(pop, 2)) 276 SELECT Completed, Requested, Completed/Requested 277 FROM m1 NATURAL LEFT JOIN m2;`, 278 } 279 res := AQLQuery{ 280 Table: "trips", 281 Joins: []Join{ 282 {Table: "trips", Alias: "rush_leg", Conditions: []string{"trips.workflow_uuid=rush_leg.workflow_uuid", "status='completed'"}}, 283 {Table: "api_cities", Alias: "cities", Conditions: []string{"cities.id=city_id"}}, 284 }, 285 Measures: []Measure{ 286 {Alias: "Completed", Expr: "count(*)", Filters: []string{"marketplace=\"agora\"", "status='completed'"}}, 287 {Alias: "Requested", Expr: "count(*)", Filters: []string{"marketplace=\"agora\""}}, 288 {Expr: "Completed/Requested"}, 289 }, 290 Dimensions: []Dimension{{Expr: "request_at", TimeBucketizer: "day", TimeUnit: "minute"}, {Expr: "pop", NumericBucketizer: NumericBucketizerDef{LogBase: 2}}}, 291 SupportingDimensions: []Dimension{}, 292 SupportingMeasures: []Measure{}, 293 TimeFilter: TimeFilter{Column: "request_at", From: "96 quarter-hours ago", To: "1 quarter-hours ago"}, 294 Timezone: "America/New_York", 295 } 296 runTest(sqls, res, logger) 297 }) 298 299 ginkgo.It("parse supporting measures should work", func() { 300 sqls := []string{ 301 // test Subquery 302 `SELECT Completed/Requested 303 FROM 304 (SELECT count(*) AS Requested 305 FROM trips 306 LEFT JOIN trips AS rush_leg 307 ON trips.workflow_uuid=rush_leg.workflow_uuid AND status='completed' 308 LEFT JOIN api_cities AS cities 309 ON cities.id=city_id 310 WHERE aql_time_filter(request_at, "96 quarter-hours ago", "1 quarter-hours ago", America/New_York) AND marketplace="agora" 311 GROUP BY aql_time_bucket_day(request_at, "minute", America/New_York), aql_numeric_bucket_logbase(pop, 2)) AS m1 312 NATURAL LEFT JOIN 313 (SELECT count(*) AS Completed 314 FROM trips 315 LEFT JOIN trips AS rush_leg 316 ON trips.workflow_uuid=rush_leg.workflow_uuid AND status='completed' 317 LEFT JOIN api_cities AS cities 318 ON cities.id=city_id 319 WHERE aql_time_filter(request_at, "96 quarter-hours ago", "1 quarter-hours ago", America/New_York) AND marketplace="agora" AND status='completed' 320 GROUP BY aql_time_bucket_day(request_at, "minute", America/New_York), aql_numeric_bucket_logbase(pop, 2)) AS m2;`, 321 // test WithQuery 322 `WITH m1 (Requested) AS (SELECT count(*) AS Requested 323 FROM trips 324 LEFT JOIN trips AS rush_leg 325 ON trips.workflow_uuid=rush_leg.workflow_uuid AND status='completed' 326 LEFT JOIN api_cities AS cities 327 ON cities.id=city_id 328 WHERE aql_time_filter(request_at, "96 quarter-hours ago", "1 quarter-hours ago", America/New_York) AND marketplace="agora" 329 GROUP BY aql_time_bucket_day(request_at, "minute", America/New_York), aql_numeric_bucket_logbase(pop, 2)), 330 m2 (Completed) AS 331 (SELECT count(*) AS Completed 332 FROM trips 333 LEFT JOIN trips AS rush_leg 334 ON trips.workflow_uuid=rush_leg.workflow_uuid AND status='completed' 335 LEFT JOIN api_cities AS cities 336 ON cities.id=city_id 337 WHERE aql_time_filter(request_at, "96 quarter-hours ago", "1 quarter-hours ago", America/New_York) AND marketplace="agora" AND status='completed' 338 GROUP BY aql_time_bucket_day(request_at, "minute", America/New_York), aql_numeric_bucket_logbase(pop, 2)) 339 SELECT Completed/Requested 340 FROM m1 NATURAL LEFT JOIN m2;`, 341 } 342 res := AQLQuery{ 343 Table: "trips", 344 Joins: []Join{ 345 {Table: "trips", Alias: "rush_leg", Conditions: []string{"trips.workflow_uuid=rush_leg.workflow_uuid", "status='completed'"}}, 346 {Table: "api_cities", Alias: "cities", Conditions: []string{"cities.id=city_id"}}, 347 }, 348 Measures: []Measure{{Expr: "Completed/Requested"}}, 349 TimeFilter: TimeFilter{Column: "request_at", From: "96 quarter-hours ago", To: "1 quarter-hours ago"}, 350 Dimensions: []Dimension{{Expr: "request_at", TimeBucketizer: "day", TimeUnit: "minute"}, {Expr: "pop", NumericBucketizer: NumericBucketizerDef{LogBase: 2}}}, 351 SupportingDimensions: []Dimension{}, 352 SupportingMeasures: []Measure{ 353 {Alias: "Requested", Expr: "count(*)", Filters: []string{"marketplace=\"agora\""}}, 354 {Alias: "Completed", Expr: "count(*)", Filters: []string{"marketplace=\"agora\"", "status='completed'"}}, 355 }, 356 Timezone: "America/New_York", 357 } 358 for _, sql := range sqls { 359 actual, err := Parse(sql, logger) 360 Ω(err).ShouldNot(BeNil()) 361 Ω(err.Error()).Should(Equal("sub query not supported yet")) 362 res.SQLQuery = sql 363 Ω(*actual).Should(BeEquivalentTo(res)) 364 } 365 }) 366 367 ginkgo.It("With RECURSIVE is not allowed", func() { 368 sqls := []string{ 369 `WITH RECURSIVE t(n) AS ( 370 VALUES (1) 371 UNION ALL 372 SELECT n+1 FROM t WHERE n < 100 373 ) 374 SELECT sum(n) FROM t;`, 375 } 376 for _, sql := range sqls { 377 actual, err := Parse(sql, logger) 378 Ω(err).ShouldNot(BeNil()) 379 Ω(err.Error()).Should(Equal("RECURSIVE not yet supported at (line:1, col:0)")) 380 Ω(actual).Should(BeNil()) 381 } 382 }) 383 384 ginkgo.It("Query in namedQuery should not contain With or queryNoWith", func() { 385 sqls := []string{ 386 `WITH m1 (Requested) AS 387 (With m (Requested) AS 388 SELECT count(*) AS Requested FROM trips 389 SELECT Requested FROM m) 390 SELECT Requested FROM m1;`, 391 } 392 for _, sql := range sqls { 393 actual, err := Parse(sql, logger) 394 Ω(err).ShouldNot(BeNil()) 395 Ω(err.Error()).Should(Equal("only support 1 level with query at (line:2, col:5)")) 396 Ω(actual).Should(BeNil()) 397 } 398 }) 399 400 ginkgo.It("Only main query allows NATURAL JOIN by using With/subqueryRelation identifier", func() { 401 sqls := []string{ 402 `WITH m1 (Requested) AS (SELECT count(*) AS Requested FROM trips), 403 m2 (Completed) AS (SELECT count(*) AS Completed FROM trips 404 NATURAL LEFT JOIN m1) 405 SELECT Completed, Requested, Completed/Requested 406 FROM m1 NATURAL LEFT JOIN m2;`, 407 } 408 for _, sql := range sqls { 409 actual, err := Parse(sql, logger) 410 Ω(err).ShouldNot(BeNil()) 411 Ω(err.Error()).Should(Equal("natural join not supported at subquery/withQuery at (line:2, col:56)")) 412 Ω(actual).Should(BeNil()) 413 } 414 }) 415 416 ginkgo.It("Both left and right in joinRelation must be either tableName or With/subqueryRelation at the same time", func() { 417 sqls := []string{ 418 `WITH m1 (f) AS (SELECT fare AS f FROM trips), 419 SELECT f, driverUuid, riderUuid 420 FROM m1 NATURAL LEFT JOIN trips;`, 421 `WITH m2 (f) AS (SELECT fare AS f FROM trips), 422 SELECT driverUuid, riderUuid, f 423 FROM trips NATURAL LEFT JOIN m2;`, 424 } 425 for _, sql := range sqls { 426 actual, err := Parse(sql, logger) 427 Ω(err).ShouldNot(BeNil()) 428 Ω(err.Error()).Should(Equal("missing with query body at (line:2, col:3)")) 429 Ω(actual).Should(BeNil()) 430 } 431 }) 432 433 ginkgo.It("FROM, GROUP BY and ORDER BY clause are required to be same in the With/subqueryRelation", func() { 434 sqls := []string{ 435 `WITH m1 (Requested) AS (SELECT count(*) AS Requested 436 FROM base_trips 437 LEFT JOIN trips AS rush_leg 438 ON trips.workflow_uuid=rush_leg.workflow_uuid AND status='completed' 439 LEFT JOIN api_cities AS cities 440 ON cities.id=city_id 441 WHERE aql_time_filter(request_at, "96 quarter-hours ago", "1 quarter-hours ago", America/New_York) AND marketplace="agora" 442 m2 (Completed) AS 443 (SELECT count(*) AS Completed 444 FROM workflow_trips 445 LEFT JOIN trips AS rush_leg 446 ON trips.workflow_uuid=rush_leg.workflow_uuid AND status='completed' 447 LEFT JOIN api_cities AS cities 448 ON cities.id=city_id 449 WHERE aql_time_filter(request_at, "96 quarter-hours ago", "1 quarter-hours ago", America/New_York) AND marketplace="agora" AND status='completed' 450 SELECT Completed/Requested 451 FROM m1 NATURAL LEFT JOIN m2;`, 452 453 `WITH m1 (Requested) AS (SELECT count(*) AS Requested 454 FROM trips 455 LEFT JOIN trips AS rush_leg 456 ON trips.workflow_uuid=rush_leg.workflow_uuid AND status='completed' 457 LEFT JOIN api_cities AS cities 458 ON cities.id=city_id 459 WHERE aql_time_filter(request_at, "96 quarter-hours ago", "1 quarter-hours ago", America/New_York) AND marketplace="agora" 460 GROUP BY aql_time_bucket_hour(request_at, "minute", America/New_York), aql_numeric_bucket_logbase(pop, 2)), 461 m2 (Completed) AS 462 (SELECT count(*) AS Completed 463 FROM trips 464 LEFT JOIN trips AS rush_leg 465 ON trips.workflow_uuid=rush_leg.workflow_uuid AND status='completed' 466 LEFT JOIN api_cities AS cities 467 ON cities.id=city_id 468 WHERE aql_time_filter(request_at, "96 quarter-hours ago", "1 quarter-hours ago", America/New_York) AND marketplace="agora" AND status='completed' 469 GROUP BY aql_time_bucket_day(request_at, "minute", America/New_York), aql_numeric_bucket_logbase(pop, 2)) 470 SELECT Completed/Requested 471 FROM m1 NATURAL LEFT JOIN m2;`, 472 } 473 for _, sql := range sqls { 474 actual, err := Parse(sql, logger) 475 Ω(err).ShouldNot(BeNil()) 476 Ω(actual).Should(BeNil()) 477 } 478 }) 479 480 ginkgo.It("The identifier of With/subqueryRelation is not allowed in expression", func() { 481 sqls := []string{ 482 `WITH m1 (avg_fare) AS 483 (SELECT avg(fare) AS avg_fare FROM trips) 484 SELECT fare FROM trips 485 WHERE fare > m1.avg_fare;`, 486 } 487 for _, sql := range sqls { 488 actual, err := Parse(sql, logger) 489 Ω(err).ShouldNot(BeNil()) 490 Ω(err.Error()).Should(Equal("subquery/withQuery identifier in expression not supported yet. (line:4, col:16)")) 491 Ω(actual).Should(BeNil()) 492 } 493 }) 494 })