Repository: prql/prql
Pull request #875 (2022-07-28 03:40:13)

Switch implicit `compile` tests to actual `compile` tests

max-sixty: I'm going to try and develop something that 
a) aggregates the tests into fewer cases
b) tests each stage of the pipeline for each case

But merging this for the moment, so we have a better place to put the simple tests

Patch:
diff --git a/prql-compiler/src/lib.rs b/prql-compiler/src/lib.rs
index a9f179e4..335e0e3c 100644
--- a/prql-compiler/src/lib.rs
+++ b/prql-compiler/src/lib.rs
@@ -47,10 +47,48 @@ pub fn from_json(json: &str) -> Result<String> {
     Ok(format!("{}", ast::Item::Query(query)))
 }
 
+// Simple tests for "this PRQL creates this SQL" go here.
 #[cfg(test)]
 mod test {
-    use super::*;
-    use crate::to_json;
+    use super::{compile, from_json, to_json, Result};
+    use insta::{assert_display_snapshot, assert_snapshot};
+
+    #[test]
+    fn test_stdlib() {
+        let query = r###"
+        from employees
+        aggregate (
+          [salary_usd = min salary]
+        )
+        "###;
+
+        let sql = compile(query).unwrap();
+        assert_snapshot!(sql,
+            @r###"
+        SELECT
+          MIN(salary) AS salary_usd
+        FROM
+          employees
+        "###
+        );
+
+        let query = r###"
+        from employees
+        aggregate (
+          [salary_usd = (round salary 2)]
+        )
+        "###;
+
+        let sql = compile(query).unwrap();
+        assert_snapshot!(sql,
+            @r###"
+        SELECT
+          ROUND(salary, 2) AS salary_usd
+        FROM
+          employees
+        "###
+        );
+    }
 
     #[test]
     fn test_to_json() -> Result<()> {
@@ -62,6 +100,837 @@ mod test {
         Ok(())
     }
 
+    #[test]
+    fn test_precedence() -> Result<()> {
+        assert_display_snapshot!((compile(r###"
+        from x
+        derive [
+          n = a + b,
+          r = a/n,
+        ]
+        select temp_c = (temp - 32) * 3
+        "###)?), @r###"
+        SELECT
+          (temp - 32) * 3 AS temp_c
+        FROM
+          x
+        "###);
+
+        assert_display_snapshot!((compile(r###"
+        func add a b -> a + b
+
+        from numbers
+        derive [sum_1 = a + b, sum_2 = add a b]
+        select [result = c * sum_1 + sum_2]
+        "###)?), @r###"
+        SELECT
+          c * (a + b) + a + b AS result
+        FROM
+          numbers
+        "###);
+
+        assert_display_snapshot!((compile(r###"
+        from numbers
+        derive [g = -a]
+        select a * g
+        "###)?), @r###"
+        SELECT
+          a * - a
+        FROM
+          numbers
+        "###);
+
+        assert_display_snapshot!((compile(r###"
+        from numbers
+        select negated_is_null = (!a) == null
+        "###)?), @r###"
+        SELECT
+          (NOT a) IS NULL AS negated_is_null
+        FROM
+          numbers
+        "###);
+
+        assert_display_snapshot!((compile(r###"
+        from numbers
+        select is_not_null = !(a == null)
+        "###)?), @r###"
+        SELECT
+          NOT a IS NULL AS is_not_null
+        FROM
+          numbers
+        "###);
+
+        assert_display_snapshot!(compile(
+            r###"
+        from numbers
+        select (a + b) == null
+        "###
+        )?, @r###"
+        SELECT
+          a + b IS NULL
+        FROM
+          numbers
+        "###
+        );
+
+        Ok(())
+    }
+    #[test]
+    fn test_pipelines() {
+        assert_display_snapshot!((compile(r###"
+        from employees
+        group dept (take 1)
+        "###).unwrap()), @r###"
+        SELECT
+          DISTINCT employees.*
+        FROM
+          employees
+        "###);
+    }
+
+    #[test]
+    fn test_rn_ids_are_unique() {
+        assert_display_snapshot!((compile(r###"
+        from y_orig
+        group [y_id] (
+          take 2 # take 1 uses `distinct` instead of partitioning, which might be a separate bug
+        )
+        group [x_id] (
+          take 3
+        )
+        "###).unwrap()), @r###"
+        WITH table_0 AS (
+          SELECT
+            y_orig.*,
+            ROW_NUMBER() OVER (PARTITION BY y_id) AS _rn_82
+          FROM
+            y_orig
+        ),
+        table_1 AS (
+          SELECT
+            table_0.*,
+            ROW_NUMBER() OVER (PARTITION BY x_id) AS _rn_83
+          FROM
+            table_0
+          WHERE
+            _rn_82 <= 2
+        )
+        SELECT
+          table_1.*
+        FROM
+          table_1
+        WHERE
+          _rn_83 <= 3
+        "###);
+    }
+
+    #[test]
+    fn test_quoting() -> Result<()> {
+        // GH-#822
+        assert_display_snapshot!((compile(r###"
+prql dialect:postgres
+from some_schema.tablename
+        "###)?), @r###"
+        SELECT
+          some_schema.tablename.*
+        FROM
+          some_schema.tablename
+        "###);
+
+        assert_display_snapshot!((compile(r###"
+prql dialect:bigquery
+from db.schema.table
+join `db.schema.table2` [id]
+join `db.schema.t-able` [id]
+        "###)?), @r###"
+        SELECT
+          `db.schema.table`.*,
+          `db.schema.table2`.*,
+          `db.schema.t-able`.*,
+          id
+        FROM
+          `db.schema.table`
+          JOIN `db.schema.table2` USING(id)
+          JOIN `db.schema.t-able` USING(id)
+        "###);
+
+        assert_display_snapshot!((compile(r###"
+from table
+select `first name`
+        "###)?), @r###"
+        SELECT
+          "first name"
+        FROM
+          table
+        "###);
+
+        Ok(())
+    }
+    #[test]
+    fn test_sorts() -> Result<()> {
+        let query = r###"
+        from invoices
+        sort [issued_at, -amount, +num_of_articles]
+        "###;
+
+        assert_display_snapshot!((compile(query)?), @r###"
+        SELECT
+          invoices.*
+        FROM
+          invoices
+        ORDER BY
+          issued_at,
+          amount DESC,
+          num_of_articles
+        "###);
+
+        Ok(())
+    }
+
+    #[test]
+    fn test_ranges() -> Result<()> {
+        let query = r###"
+        from employees
+        filter (age | in 18..40)
+        "###;
+
+        assert_display_snapshot!((compile(query)?), @r###"
+        SELECT
+          employees.*
+        FROM
+          employees
+        WHERE
+          age BETWEEN 18
+          AND 40
+        "###);
+
+        let query = r###"
+        from employees
+        filter (age | in ..40)
+        "###;
+
+        assert!(compile(query).is_err());
+
+        let query = r###"
+        from events
+        filter (date | in @1776-07-04..@1787-09-17)
+        "###;
+
+        assert_display_snapshot!((compile(query)?), @r###"
+        SELECT
+          events.*
+        FROM
+          events
+        WHERE
+          date BETWEEN DATE '1776-07-04'
+          AND DATE '1787-09-17'
+        "###);
+
+        Ok(())
+    }
+
+    #[test]
+    fn test_interval() -> Result<()> {
+        let query = r###"
+        from projects
+        derive first_check_in = start + 10days
+        "###;
+
+        assert_display_snapshot!((compile(query)?), @r###"
+        SELECT
+          projects.*,
+          start + INTERVAL '10' DAY AS first_check_in
+        FROM
+          projects
+        "###);
+
+        Ok(())
+    }
+
+    #[test]
+    fn test_dates() -> Result<()> {
+        let query = r###"
+        derive [
+            date = @2011-02-01,
+            timestamp = @2011-02-01T10:00,
+            time = @14:00,
+            # datetime = @2011-02-01T10:00<datetime>,
+        ]
+
+        "###;
+
+        assert_display_snapshot!((compile(query)?), @r###"
+        SELECT
+          DATE '2011-02-01' AS date,
+          TIMESTAMP '2011-02-01T10:00' AS timestamp,
+          TIME '14:00' AS time
+        "###);
+
+        Ok(())
+    }
+
+    #[test]
+    fn test_window_functions() {
+        let query = r###"
+        from employees
+        group last_name (
+            derive count
+        )
+        "###;
+
+        assert_display_snapshot!((compile(query).unwrap()), @r###"
+        SELECT
+          employees.*,
+          COUNT(*) OVER (PARTITION BY last_name)
+        FROM
+          employees
+        "###);
+
+        let query = r###"
+        from co=cust_order
+        join ol=order_line [order_id]
+        derive [
+          order_month = s"TO_CHAR({co.order_date}, '%Y-%m')",
+          order_day = s"TO_CHAR({co.order_date}, '%Y-%m-%d')",
+        ]
+        group [order_month, order_day] (
+          aggregate [
+            num_orders = s"COUNT(DISTINCT {co.order_id})",
+            num_books = count non_null:ol.book_id,
+            total_price = sum ol.price,
+          ]
+        )
+        group [order_month] (
+          sort order_day
+          window expanding:true (
+            derive [running_total_num_books = sum num_books]
+          )
+        )
+        sort order_day
+        derive [num_books_last_week = lag 7 num_books]
+        "###;
+
+        assert_display_snapshot!((compile(query).unwrap()), @r###"
+        SELECT
+          TO_CHAR(co.order_date, '%Y-%m') AS order_month,
+          TO_CHAR(co.order_date, '%Y-%m-%d') AS order_day,
+          COUNT(DISTINCT co.order_id) AS num_orders,
+          COUNT(ol.book_id) AS num_books,
+          SUM(ol.price) AS total_price,
+          SUM(COUNT(ol.book_id)) OVER (
+            PARTITION BY TO_CHAR(co.order_date, '%Y-%m')
+            ORDER BY
+              TO_CHAR(co.order_date, '%Y-%m-%d') ROWS BETWEEN UNBOUNDED PRECEDING
+              AND CURRENT ROW
+          ) AS running_total_num_books,
+          LAG(COUNT(ol.book_id), 7) OVER (
+            ORDER BY
+              TO_CHAR(co.order_date, '%Y-%m-%d') ROWS BETWEEN UNBOUNDED PRECEDING
+              AND UNBOUNDED FOLLOWING
+          ) AS num_books_last_week
+        FROM
+          cust_order AS co
+          JOIN order_line AS ol USING(order_id)
+        GROUP BY
+          TO_CHAR(co.order_date, '%Y-%m'),
+          TO_CHAR(co.order_date, '%Y-%m-%d')
+        ORDER BY
+          order_day
+        "###);
+
+        // lag must be recognized as window function, even outside of group context
+        // rank must not have two OVER clauses
+        let query = r###"
+        from daily_orders
+        derive [last_week = lag 7 num_orders]
+        group month ( derive [total_month = sum num_orders])
+        "###;
+
+        assert_display_snapshot!((compile(query).unwrap()), @r###"
+        SELECT
+          daily_orders.*,
+          LAG(num_orders, 7) OVER () AS last_week,
+          SUM(num_orders) OVER (PARTITION BY month) AS total_month
+        FROM
+          daily_orders
+        "###);
+
+        // sort does not affects into groups, group undoes sorting
+        let query = r###"
+        from daily_orders
+        sort day
+        group month (derive [total_month = rank])
+        derive [last_week = lag 7 num_orders]
+        "###;
+
+        assert_display_snapshot!((compile(query).unwrap()), @r###"
+        SELECT
+          daily_orders.*,
+          RANK() OVER (PARTITION BY month) AS total_month,
+          LAG(num_orders, 7) OVER () AS last_week
+        FROM
+          daily_orders
+        ORDER BY
+          day
+        "###);
+
+        // sort does not leak out of groups
+        let query = r###"
+        from daily_orders
+        sort day
+        group month (sort num_orders | window expanding:true (derive rank))
+        derive [num_orders_last_week = lag 7 num_orders]
+        "###;
+        assert_display_snapshot!((compile(query).unwrap()), @r###"
+        SELECT
+          daily_orders.*,
+          RANK() OVER (
+            PARTITION BY month
+            ORDER BY
+              num_orders ROWS BETWEEN UNBOUNDED PRECEDING
+              AND CURRENT ROW
+          ),
+          LAG(num_orders, 7) OVER () AS num_orders_last_week
+        FROM
+          daily_orders
+        "###);
+    }
+
+    #[test]
+    fn test_window_functions_2() {
+        // detect sum as a window function, even without group or window
+        assert_display_snapshot!((compile(r###"
+        from foo
+        derive [a = sum b]
+        group c (
+            derive [d = sum b]
+        )
+        "###).unwrap()), @r###"
+        SELECT
+          foo.*,
+          SUM(b) OVER () AS a,
+          SUM(b) OVER (PARTITION BY c) AS d
+        FROM
+          foo
+        "###);
+
+        assert_display_snapshot!((compile(r###"
+        from foo
+        window expanding:true (
+            derive [running_total = sum b]
+        )
+        "###).unwrap()), @r###"
+        SELECT
+          foo.*,
+          SUM(b) OVER (
+            ROWS BETWEEN UNBOUNDED PRECEDING
+            AND CURRENT ROW
+          ) AS running_total
+        FROM
+          foo
+        "###);
+
+        assert_display_snapshot!((compile(r###"
+        from foo
+        window rolling:3 (
+            derive [last_three = sum b]
+        )
+        "###).unwrap()), @r###"
+        SELECT
+          foo.*,
+          SUM(b) OVER (
+            ROWS BETWEEN 2 PRECEDING
+            AND CURRENT ROW
+          ) AS last_three
+        FROM
+          foo
+        "###);
+
+        assert_display_snapshot!((compile(r###"
+        from foo
+        window rows:0..4 (
+            derive [next_four_rows = sum b]
+        )
+        "###).unwrap()), @r###"
+        SELECT
+          foo.*,
+          SUM(b) OVER (
+            ROWS BETWEEN CURRENT ROW
+            AND 4 FOLLOWING
+          ) AS next_four_rows
+        FROM
+          foo
+        "###);
+
+        assert_display_snapshot!((compile(r###"
+        from foo
+        sort day
+        window range:-4..4 (
+            derive [next_four_days = sum b]
+        )
+        "###).unwrap()), @r###"
+        SELECT
+          foo.*,
+          SUM(b) OVER (
+            ORDER BY
+              day RANGE BETWEEN 4 PRECEDING
+              AND 4 FOLLOWING
+          ) AS next_four_days
+        FROM
+          foo
+        "###);
+
+        // TODO: add test for preceding
+    }
+
+    #[test]
+    fn test_strings() -> Result<()> {
+        let query = r###"
+        derive [
+            x = "two households'",
+            y = 'two households"',
+            z = f"a {x} b' {y} c",
+            v = f'a {x} b" {y} c',
+        ]
+        "###;
+        assert_display_snapshot!((compile(query)?), @r###"
+        SELECT
+          'two households''' AS x,
+          'two households"' AS y,
+          CONCAT(
+            'a ',
+            'two households''',
+            ' b'' ',
+            'two households"',
+            ' c'
+          ) AS z,
+          CONCAT(
+            'a ',
+            'two households''',
+            ' b" ',
+            'two households"',
+            ' c'
+          ) AS v
+        "###);
+
+        Ok(())
+    }
+
+    #[test]
+    fn test_filter() {
+        // https://github.com/prql/prql/issues/469
+        let query = r###"
+        from employees
+        filter [age > 25, age < 40]
+        "###;
+
+        assert!(compile(query).is_err());
+
+        assert_display_snapshot!((compile(r###"
+        from employees
+        filter age > 25 and age < 40
+        "###).unwrap()), @r###"
+        SELECT
+          employees.*
+        FROM
+          employees
+        WHERE
+          age > 25
+          AND age < 40
+        "###);
+
+        assert_display_snapshot!((compile(r###"
+        from employees
+        filter age > 25
+        filter age < 40
+        "###).unwrap()), @r###"
+        SELECT
+          employees.*
+        FROM
+          employees
+        WHERE
+          age > 25
+          AND age < 40
+        "###);
+    }
+
+    #[test]
+    fn test_nulls() -> Result<()> {
+        assert_display_snapshot!((compile(r###"
+        from employees
+        select amount = null
+        "###)?), @r###"
+        SELECT
+          NULL AS amount
+        FROM
+          employees
+        "###);
+
+        // coalesce
+        assert_display_snapshot!((compile(r###"
+        from employees
+        derive amount = amount + 2 ?? 3 * 5
+        "###)?), @r###"
+        SELECT
+          employees.*,
+          COALESCE(amount + 2, 3 * 5) AS amount
+        FROM
+          employees
+        "###);
+
+        // IS NULL
+        assert_display_snapshot!((compile(r###"
+        from employees
+        filter first_name == null and null == last_name
+        "###)?), @r###"
+        SELECT
+          employees.*
+        FROM
+          employees
+        WHERE
+          first_name IS NULL
+          AND last_name IS NULL
+        "###);
+
+        // IS NOT NULL
+        assert_display_snapshot!((compile(r###"
+        from employees
+        filter first_name != null and null != last_name
+        "###)?), @r###"
+        SELECT
+          employees.*
+        FROM
+          employees
+        WHERE
+          first_name IS NOT NULL
+          AND last_name IS NOT NULL
+        "###);
+
+        Ok(())
+    }
+
+    #[test]
+    fn test_range() -> Result<()> {
+        assert_display_snapshot!((compile(r###"
+        from employees
+        take ..10
+        "###)?), @r###"
+        SELECT
+          employees.*
+        FROM
+          employees
+        LIMIT
+          10
+        "###);
+
+        assert_display_snapshot!((compile(r###"
+        from employees
+        take 5..10
+        "###)?), @r###"
+        SELECT
+          employees.*
+        FROM
+          employees
+        LIMIT
+          6 OFFSET 4
+        "###);
+
+        assert_display_snapshot!((compile(r###"
+        from employees
+        take 5..
+        "###)?), @r###"
+        SELECT
+          employees.*
+        FROM
+          employees OFFSET 4
+        "###);
+
+        // should be one SELECT
+        assert_display_snapshot!((compile(r###"
+        from employees
+        take 11..20
+        take 1..5
+        "###)?), @r###"
+        SELECT
+          employees.*
+        FROM
+          employees
+        LIMIT
+          5 OFFSET 10
+        "###);
+
+        // should be two SELECTs
+        assert_display_snapshot!((compile(r###"
+        from employees
+        take 11..20
+        sort name
+        take 1..5
+        "###)?), @r###"
+        WITH table_0 AS (
+          SELECT
+            employees.*
+          FROM
+            employees
+          LIMIT
+            10 OFFSET 10
+        )
+        SELECT
+          table_0.*
+        FROM
+          table_0
+        ORDER BY
+          name
+        LIMIT
+          5
+        "###);
+
+        Ok(())
+    }
+
+    #[test]
+    fn test_distinct() {
+        // window functions cannot materialize into where statement: CTE is needed
+        assert_display_snapshot!((compile(r###"
+        from employees
+        derive rn = row_number
+        filter rn > 2
+        "###).unwrap()), @r###"
+        WITH table_0 AS (
+          SELECT
+            employees.*,
+            ROW_NUMBER() OVER () AS rn
+          FROM
+            employees
+        )
+        SELECT
+          table_0.*
+        FROM
+          table_0
+        WHERE
+          rn > 2
+        "###);
+
+        // basic distinct
+        assert_display_snapshot!((compile(r###"
+        from employees
+        select first_name
+        group first_name (take 1)
+        "###).unwrap()), @r###"
+        SELECT
+          DISTINCT first_name
+        FROM
+          employees
+        "###);
+
+        // distinct on two columns
+        assert_display_snapshot!((compile(r###"
+        from employees
+        select [first_name, last_name]
+        group [first_name, last_name] (take 1)
+        "###).unwrap()), @r###"
+        SELECT
+          DISTINCT first_name,
+          last_name
+        FROM
+          employees
+        "###);
+
+        // TODO: this should not use DISTINCT but ROW_NUMBER and WHERE, because we want
+        // row  distinct only over first_name and last_name.
+        assert_display_snapshot!((compile(r###"
+        from employees
+        group [first_name, last_name] (take 1)
+        "###).unwrap()), @r###"
+        SELECT
+          DISTINCT employees.*
+        FROM
+          employees
+        "###);
+
+        // head
+        assert_display_snapshot!((compile(r###"
+        from employees
+        group department (take 3)
+        "###).unwrap()), @r###"
+        WITH table_0 AS (
+          SELECT
+            employees.*,
+            ROW_NUMBER() OVER (PARTITION BY department) AS _rn_81
+          FROM
+            employees
+        )
+        SELECT
+          table_0.*
+        FROM
+          table_0
+        WHERE
+          _rn_81 <= 3
+        "###);
+
+        assert_display_snapshot!((compile(r###"
+        from employees
+        group department (sort salary | take 2..3)
+        "###).unwrap()), @r###"
+        WITH table_0 AS (
+          SELECT
+            employees.*,
+            ROW_NUMBER() OVER (
+              PARTITION BY department
+              ORDER BY
+                salary
+            ) AS _rn_82
+          FROM
+            employees
+        )
+        SELECT
+          table_0.*
+        FROM
+          table_0
+        WHERE
+          _rn_82 BETWEEN 2
+          AND 3
+        "###);
+    }
+
+    #[test]
+    fn test_dbt_query() {
+        assert_display_snapshot!((compile(r###"
+        from {{ ref('stg_orders') }}
+        aggregate (min order_id)
+        "###).unwrap()), @r###"
+        SELECT
+          MIN(order_id)
+        FROM
+          {{ ref('stg_orders') }}
+        "###);
+    }
+
+    #[test]
+    fn test_join() -> Result<()> {
+        assert_display_snapshot!((compile(r###"
+        from x
+        join y [id]
+        "###)?), @r###"
+        SELECT
+          x.*,
+          y.*,
+          id
+        FROM
+          x
+          JOIN y USING(id)
+        "###);
+
+        // TODO: is there a better way to format the errors? `anyhow::Error`
+        // doesn't seem to serialize. We'd really like to show and test the
+        // error messages in our test suite.
+        assert_snapshot!((compile(r###"
+        from x
+        join y [x.id]
+        "###).unwrap_err().to_string()), @r###"Error { span: None, reason: Expected { who: Some("join"), expected: "An identifer with only one part; no `.`", found: "A multipart identifer" }, help: None }"###);
+
+        Ok(())
+    }
+
     #[test]
     fn test_from_json() -> Result<()> {
         // Test that the SQL generated from the JSON of the PRQL is the same as the raw PRQL
@@ -96,4 +965,489 @@ select [mng_name, managers.gender, salary_avg, salary_sd]"#;
         assert_eq!(sql_from_prql, sql_from_json);
         Ok(())
     }
+    #[test]
+    fn test_f_string() {
+        let query = r###"
+        from employees
+        derive age = year_born - s'now()'
+        select [
+            f"Hello my name is {prefix}{first_name} {last_name}",
+            f"and I am {age} years old."
+        ]
+        "###;
+
+        let sql = compile(query).unwrap();
+        assert_display_snapshot!(sql,
+            @r###"
+        SELECT
+          CONCAT(
+            'Hello my name is ',
+            prefix,
+            first_name,
+            ' ',
+            last_name
+          ),
+          CONCAT('and I am ', year_born - now(), ' years old.')
+        FROM
+          employees
+        "###
+        );
+    }
+
+    #[test]
+    fn test_sql_of_ast_1() -> Result<()> {
+        let query = r###"
+        from employees
+        filter country == "USA"
+        group [title, country] (
+            aggregate [average salary]
+        )
+        sort title
+        take 20
+        "###;
+
+        let sql = compile(query)?;
+        assert_display_snapshot!(sql,
+            @r###"
+        SELECT
+          title,
+          country,
+          AVG(salary)
+        FROM
+          employees
+        WHERE
+          country = 'USA'
+        GROUP BY
+          title,
+          country
+        ORDER BY
+          title
+        LIMIT
+          20
+        "###
+        );
+        Ok(())
+    }
+
+    #[test]
+    fn test_sql_of_ast_2() -> Result<()> {
+        let query = r###"
+        from employees
+        aggregate sum_salary = s"count({salary})"
+        filter sum_salary > 100
+        "###;
+        let sql = compile(query)?;
+        assert_snapshot!(sql, @r###"
+        SELECT
+          count(salary) AS sum_salary
+        FROM
+          employees
+        HAVING
+          count(salary) > 100
+        "###);
+        assert!(sql.to_lowercase().contains(&"having".to_lowercase()));
+
+        Ok(())
+    }
+
+    #[test]
+    fn test_prql_to_sql_1() -> Result<()> {
+        let query = r#"
+    from employees
+    aggregate [
+      count non_null:salary,
+      sum salary,
+    ]
+    "#;
+        let sql = compile(query)?;
+        assert_display_snapshot!(sql,
+            @r###"
+        SELECT
+          COUNT(salary),
+          SUM(salary)
+        FROM
+          employees
+        "###
+        );
+        Ok(())
+    }
+
+    #[test]
+    fn test_prql_to_sql_2() -> Result<()> {
+        let query = r#"
+from employees
+filter country == "USA"                           # Each line transforms the previous result.
+derive [                                         # This adds columns / variables.
+  gross_salary = salary + payroll_tax,
+  gross_cost = gross_salary + benefits_cost      # Variables can use other variables.
+]
+filter gross_cost > 0
+group [title, country] (
+    aggregate  [                                 # `by` are the columns to group by.
+        average salary,                          # These are aggregation calcs run on each group.
+        sum     salary,
+        average gross_salary,
+        sum     gross_salary,
+        average gross_cost,
+        sum_gross_cost = sum gross_cost,
+        ct = count,
+    ]
+)
+sort sum_gross_cost
+filter ct > 200
+take 20
+"#;
+
+        let sql = compile(query)?;
+        assert_display_snapshot!(sql);
+        Ok(())
+    }
+
+    #[test]
+    fn test_prql_to_sql_table() -> Result<()> {
+        // table
+        let query = r#"
+        table newest_employees = (
+            from employees
+            sort tenure
+            take 50
+        )
+        table average_salaries = (
+            from salaries
+            group country (
+                aggregate [
+                    average_country_salary = average salary
+                ]
+            )
+        )
+        from newest_employees
+        join average_salaries [country]
+        select [name, salary, average_country_salary]
+        "#;
+        let sql = compile(query)?;
+        assert_display_snapshot!(sql,
+            @r###"
+        WITH newest_employees AS (
+          SELECT
+            employees.*
+          FROM
+            employees
+          ORDER BY
+            tenure
+          LIMIT
+            50
+        ), average_salaries AS (
+          SELECT
+            country,
+            AVG(salary) AS average_country_salary
+          FROM
+            salaries
+          GROUP BY
+            country
+        )
+        SELECT
+          name,
+          average_salaries.salary,
+          average_salaries.average_country_salary
+        FROM
+          newest_employees
+          JOIN average_salaries USING(country)
+        "###
+        );
+
+        Ok(())
+    }
+
+    #[test]
+    fn test_nonatomic() -> Result<()> {
+        // A take, then two aggregates
+        let query = r###"
+            from employees
+            take 20
+            filter country == "USA"
+            group [title, country] (
+                aggregate [
+                    salary = average salary
+                ]
+            )
+            group [title, country] (
+                aggregate [
+                    sum_gross_cost = average salary
+                ]
+            )
+            sort sum_gross_cost
+        "###;
+
+        assert_display_snapshot!((compile(query)?), @r###"
+        WITH table_0 AS (
+          SELECT
+            employees.*
+          FROM
+            employees
+          LIMIT
+            20
+        ), table_1 AS (
+          SELECT
+            title,
+            country,
+            AVG(salary) AS salary
+          FROM
+            table_0
+          WHERE
+            country = 'USA'
+          GROUP BY
+            title,
+            country
+        )
+        SELECT
+          title,
+          country,
+          AVG(salary) AS sum_gross_cost
+        FROM
+          table_1
+        GROUP BY
+          title,
+          country
+        ORDER BY
+          sum_gross_cost
+        "###);
+
+        Ok(())
+    }
+
+    #[test]
+    /// Confirm a nonatomic table works.
+    fn test_nonatomic_table() -> Result<()> {
+        // A take, then two aggregates
+        let query = r###"
+        table a = (
+            from employees
+            take 50
+            aggregate [s"count(*)"]
+        )
+        from a
+        join b [country]
+        select [name, salary, average_country_salary]
+"###;
+
+        assert_display_snapshot!((compile(query)?), @r###"
+        WITH table_0 AS (
+          SELECT
+            employees.*
+          FROM
+            employees
+          LIMIT
+            50
+        ), a AS (
+          SELECT
+            count(*)
+          FROM
+            table_0
+        )
+        SELECT
+          name,
+          salary,
+          average_country_salary
+        FROM
+          a
+          JOIN b USING(country)
+        "###);
+
+        Ok(())
+    }
+
+    #[test]
+    fn test_table_names_between_splits() {
+        let prql = r###"
+        from employees
+        join d=department [dept_no]
+        take 10
+        join s=salaries [emp_no]
+        select [employees.emp_no, d.name, s.salary]
+        "###;
+        let result = compile(prql).unwrap();
+        assert_display_snapshot!(result, @r###"
+        WITH table_0 AS (
+          SELECT
+            employees.*,
+            d.*,
+            dept_no
+          FROM
+            employees
+            JOIN department AS d USING(dept_no)
+          LIMIT
+            10
+        )
+        SELECT
+          table_0.emp_no,
+          table_0.name,
+          s.salary
+        FROM
+          table_0
+          JOIN salaries AS s USING(emp_no)
+        "###);
+
+        let prql = r###"
+        from e=employees
+        take 10
+        join salaries [emp_no]
+        select [e.*, salary]
+        "###;
+        let result = compile(prql).unwrap();
+        assert_display_snapshot!(result, @r###"
+        WITH table_0 AS (
+          SELECT
+            e.*
+          FROM
+            employees AS e
+          LIMIT
+            10
+        )
+        SELECT
+          table_0.*,
+          salary
+        FROM
+          table_0
+          JOIN salaries USING(emp_no)
+        "###);
+    }
+
+    #[test]
+    fn test_table_alias() -> Result<()> {
+        // Alias on from
+        let query = r###"
+            from e = employees
+            join salaries side:left [salaries.emp_no == e.emp_no]
+            group [e.emp_no] (
+                aggregate [
+                    emp_salary = average salary
+                ]
+            )
+            select [e.emp_no, emp_salary]
+        "###;
+
+        assert_display_snapshot!((compile(query)?), @r###"
+        SELECT
+          e.emp_no,
+          AVG(salary) AS emp_salary
+        FROM
+          employees AS e
+          LEFT JOIN salaries ON salaries.emp_no = e.emp_no
+        GROUP BY
+          e.emp_no
+        "###);
+        Ok(())
+    }
+
+    #[test]
+    fn test_dialects() -> Result<()> {
+        // Generic
+        let query = r###"
+        prql dialect:generic
+        from Employees
+        select [FirstName, `last name`]
+        take 3
+        "###;
+
+        assert_display_snapshot!((compile(query)?), @r###"
+        SELECT
+          "FirstName",
+          "last name"
+        FROM
+          "Employees"
+        LIMIT
+          3
+        "###);
+
+        // SQL server
+        let query = r###"
+        prql dialect:mssql
+        from Employees
+        select [FirstName, `last name`]
+        take 3
+        "###;
+
+        assert_display_snapshot!((compile(query)?), @r###"
+        SELECT
+          TOP (3) "FirstName",
+          "last name"
+        FROM
+          "Employees"
+        "###);
+
+        // MySQL
+        let query = r###"
+        prql dialect:mysql
+        from Employees
+        select [FirstName, `last name`]
+        take 3
+        "###;
+
+        assert_display_snapshot!((compile(query)?), @r###"
+        SELECT
+          `FirstName`,
+          `last name`
+        FROM
+          `Employees`
+        LIMIT
+          3
+        "###);
+
+        Ok(())
+    }
+
+    #[test]
+    fn test_ident_escaping() -> Result<()> {
+        // Generic
+        let query = r###"
+        from `anim"ls`
+        derive [`čebela` = BeeName, medved = `bear's_name`]
+        "###;
+
+        assert_display_snapshot!((compile(query)?), @r###"
+        SELECT
+          "anim""ls".*,
+          "BeeName" AS "čebela",
+          "bear's_name" AS medved
+        FROM
+          "anim""ls"
+        "###);
+
+        // MySQL
+        let query = r###"
+        prql dialect:mysql
+
+        from `anim"ls`
+        derive [`čebela` = BeeName, medved = `bear's_name`]
+        "###;
+
+        assert_display_snapshot!((compile(query)?), @r###"
+        SELECT
+          `anim"ls`.*,
+          `BeeName` AS `čebela`,
+          `bear's_name` AS medved
+        FROM
+          `anim"ls`
+        "###);
+
+        Ok(())
+    }
+    #[test]
+    fn test_literal() {
+        let query = r###"
+        from employees
+        derive [always_true = true]
+        "###;
+
+        let sql = compile(query).unwrap();
+        assert_display_snapshot!(sql,
+            @r###"
+        SELECT
+          employees.*,
+          true AS always_true
+        FROM
+          employees
+        "###
+        );
+    }
 }
diff --git a/prql-compiler/src/sql/translator.rs b/prql-compiler/src/sql/translator.rs
index 9a790f9f..dcd3966b 100644
--- a/prql-compiler/src/sql/translator.rs
+++ b/prql-compiler/src/sql/translator.rs
@@ -919,75 +919,10 @@ impl From<Vec<Node>> for AtomicTable {
 #[cfg(test)]
 mod test {
     use super::*;
-    use crate::{parser::parse, resolve, resolve_and_translate};
-    use insta::{assert_display_snapshot, assert_snapshot, assert_yaml_snapshot};
+    use crate::{parser::parse, resolve};
+    use insta::assert_yaml_snapshot;
     use serde_yaml::from_str;
 
-    #[test]
-    fn test_literal() {
-        let query: Query = parse(
-            r###"
-        from employees
-        derive [always_true = true]
-        "###,
-        )
-        .unwrap();
-
-        let sql = resolve_and_translate(query).unwrap();
-        assert_display_snapshot!(sql,
-            @r###"
-        SELECT
-          employees.*,
-          true AS always_true
-        FROM
-          employees
-        "###
-        );
-    }
-
-    #[test]
-    fn test_stdlib() {
-        let query: Query = parse(
-            r###"
-        from employees
-        aggregate (
-          [salary_usd = min salary]
-        )
-        "###,
-        )
-        .unwrap();
-
-        let sql = resolve_and_translate(query).unwrap();
-        assert_snapshot!(sql,
-            @r###"
-        SELECT
-          MIN(salary) AS salary_usd
-        FROM
-          employees
-        "###
-        );
-
-        let query: Query = parse(
-            r###"
-        from employees
-        aggregate (
-          [salary_usd = (round salary 2)]
-        )
-        "###,
-        )
-        .unwrap();
-
-        let sql = resolve_and_translate(query).unwrap();
-        assert_snapshot!(sql,
-            @r###"
-        SELECT
-          ROUND(salary, 2) AS salary_usd
-        FROM
-          employees
-        "###
-        );
-    }
-
     #[test]
     fn test_range_of_ranges() -> Result<()> {
         let range1 = Range::from_ints(Some(1), Some(10));
@@ -1051,62 +986,6 @@ mod test {
         Ok(())
     }
 
-    #[test]
-    fn test_try_from_s_string_to_expr() -> Result<()> {
-        let dialect = Dialect::Generic.handler();
-        let ast: Node = from_str(
-            r"
-        SString:
-        - String: SUM(
-        - Expr:
-            Ident: col
-        - String: )
-        ",
-        )?;
-        let expr: Expr = translate_item(ast.item, dialect.as_ref())?;
-        assert_yaml_snapshot!(
-            expr, @r###"
-        ---
-        Identifier:
-          value: SUM(col)
-          quote_style: ~
-        "###
-        );
-        Ok(())
-    }
-
-    #[test]
-    fn test_f_string() {
-        let query: Query = parse(
-            r###"
-        from employees
-        derive age = year_born - s'now()'
-        select [
-            f"Hello my name is {prefix}{first_name} {last_name}",
-            f"and I am {age} years old."
-        ]
-        "###,
-        )
-        .unwrap();
-
-        let sql = resolve_and_translate(query).unwrap();
-        assert_display_snapshot!(sql,
-            @r###"
-        SELECT
-          CONCAT(
-            'Hello my name is ',
-            prefix,
-            first_name,
-            ' ',
-            last_name
-          ),
-          CONCAT('and I am ', year_born - now(), ' years old.')
-        FROM
-          employees
-        "###
-        );
-    }
-
     fn parse_and_resolve(prql: &str) -> Result<Pipeline> {
         let (mut nodes, _) = resolve(parse(prql)?.nodes, None)?;
         let pipeline = nodes.remove(nodes.len() - 1).coerce_to_pipeline();
@@ -1169,1371 +1048,27 @@ mod test {
         assert_eq!(queries.len(), 1);
         Ok(())
     }
-
-    #[test]
-    fn test_sql_of_ast_1() -> Result<()> {
-        let query: Query = parse(
-            r###"
-        from employees
-        filter country == "USA"
-        group [title, country] (
-            aggregate [average salary]
-        )
-        sort title
-        take 20
-        "###,
-        )?;
-
-        let sql = resolve_and_translate(query)?;
-        assert_display_snapshot!(sql,
-            @r###"
-        SELECT
-          title,
-          country,
-          AVG(salary)
-        FROM
-          employees
-        WHERE
-          country = 'USA'
-        GROUP BY
-          title,
-          country
-        ORDER BY
-          title
-        LIMIT
-          20
-        "###
-        );
-        Ok(())
-    }
-
-    #[test]
-    fn test_sql_of_ast_2() -> Result<()> {
-        let query: Query = parse(
-            r###"
-        from employees
-        aggregate sum_salary = s"count({salary})"
-        filter sum_salary > 100
-        "###,
-        )?;
-        let sql = resolve_and_translate(query)?;
-        assert_snapshot!(sql, @r###"
-        SELECT
-          count(salary) AS sum_salary
-        FROM
-          employees
-        HAVING
-          count(salary) > 100
-        "###);
-        assert!(sql.to_lowercase().contains(&"having".to_lowercase()));
-
-        Ok(())
-    }
-
-    #[test]
-    fn test_prql_to_sql_1() -> Result<()> {
-        let query = parse(
-            r#"
-    from employees
-    aggregate [
-      count non_null:salary,
-      sum salary,
-    ]
-    "#,
-        )?;
-        let sql = resolve_and_translate(query)?;
-        assert_display_snapshot!(sql,
-            @r###"
-        SELECT
-          COUNT(salary),
-          SUM(salary)
-        FROM
-          employees
-        "###
-        );
-        Ok(())
-    }
-
-    #[test]
-    fn test_prql_to_sql_2() -> Result<()> {
-        let query = parse(
-            r#"
-from employees
-filter country == "USA"                           # Each line transforms the previous result.
-derive [                                         # This adds columns / variables.
-  gross_salary = salary + payroll_tax,
-  gross_cost = gross_salary + benefits_cost      # Variables can use other variables.
-]
-filter gross_cost > 0
-group [title, country] (
-    aggregate  [                                 # `by` are the columns to group by.
-        average salary,                          # These are aggregation calcs run on each group.
-        sum     salary,
-        average gross_salary,
-        sum     gross_salary,
-        average gross_cost,
-        sum_gross_cost = sum gross_cost,
-        ct = count,
-    ]
-)
-sort sum_gross_cost
-filter ct > 200
-take 20
-"#,
-        )?;
-
-        let sql = resolve_and_translate(query)?;
-        assert_display_snapshot!(sql);
-        Ok(())
-    }
-
     #[test]
-    fn test_prql_to_sql_table() -> Result<()> {
-        // table
-        let query = parse(
-            r#"
-        table newest_employees = (
-            from employees
-            sort tenure
-            take 50
-        )
-        table average_salaries = (
-            from salaries
-            group country (
-                aggregate [
-                    average_country_salary = average salary
-                ]
-            )
-        )
-        from newest_employees
-        join average_salaries [country]
-        select [name, salary, average_country_salary]
-        "#,
+    fn test_try_from_s_string_to_expr() -> Result<()> {
+        let dialect = Dialect::Generic.handler();
+        let ast: Node = from_str(
+            r"
+        SString:
+        - String: SUM(
+        - Expr:
+            Ident: col
+        - String: )
+        ",
         )?;
-        let sql = resolve_and_translate(query)?;
-        assert_display_snapshot!(sql,
-            @r###"
-        WITH newest_employees AS (
-          SELECT
-            employees.*
-          FROM
-            employees
-          ORDER BY
-            tenure
-          LIMIT
-            50
-        ), average_salaries AS (
-          SELECT
-            country,
-            AVG(salary) AS average_country_salary
-          FROM
-            salaries
-          GROUP BY
-            country
-        )
-        SELECT
-          name,
-          average_salaries.salary,
-          average_salaries.average_country_salary
-        FROM
-          newest_employees
-          JOIN average_salaries USING(country)
+        let expr: Expr = translate_item(ast.item, dialect.as_ref())?;
+        assert_yaml_snapshot!(
+            expr, @r###"
+        ---
+        Identifier:
+          value: SUM(col)
+          quote_style: ~
         "###
         );
-
-        Ok(())
-    }
-
-    #[test]
-    fn test_nonatomic() -> Result<()> {
-        // A take, then two aggregates
-        let query: Query = parse(
-            r###"
-            from employees
-            take 20
-            filter country == "USA"
-            group [title, country] (
-                aggregate [
-                    salary = average salary
-                ]
-            )
-            group [title, country] (
-                aggregate [
-                    sum_gross_cost = average salary
-                ]
-            )
-            sort sum_gross_cost
-        "###,
-        )?;
-
-        assert_display_snapshot!((resolve_and_translate(query)?), @r###"
-        WITH table_0 AS (
-          SELECT
-            employees.*
-          FROM
-            employees
-          LIMIT
-            20
-        ), table_1 AS (
-          SELECT
-            title,
-            country,
-            AVG(salary) AS salary
-          FROM
-            table_0
-          WHERE
-            country = 'USA'
-          GROUP BY
-            title,
-            country
-        )
-        SELECT
-          title,
-          country,
-          AVG(salary) AS sum_gross_cost
-        FROM
-          table_1
-        GROUP BY
-          title,
-          country
-        ORDER BY
-          sum_gross_cost
-        "###);
-
-        Ok(())
-    }
-
-    #[test]
-    /// Confirm a nonatomic table works.
-    fn test_nonatomic_table() -> Result<()> {
-        // A take, then two aggregates
-        let query = parse(
-            r###"
-        table a = (
-            from employees
-            take 50
-            aggregate [s"count(*)"]
-        )
-        from a
-        join b [country]
-        select [name, salary, average_country_salary]
-"###,
-        )?;
-
-        assert_display_snapshot!((resolve_and_translate(query)?), @r###"
-        WITH table_0 AS (
-          SELECT
-            employees.*
-          FROM
-            employees
-          LIMIT
-            50
-        ), a AS (
-          SELECT
-            count(*)
-          FROM
-            table_0
-        )
-        SELECT
-          name,
-          salary,
-          average_country_salary
-        FROM
-          a
-          JOIN b USING(country)
-        "###);
-
-        Ok(())
-    }
-
-    #[test]
-    fn test_table_names_between_splits() {
-        let prql = r###"
-        from employees
-        join d=department [dept_no]
-        take 10
-        join s=salaries [emp_no]
-        select [employees.emp_no, d.name, s.salary]
-        "###;
-        let result = parse(prql).and_then(resolve_and_translate).unwrap();
-        assert_display_snapshot!(result, @r###"
-        WITH table_0 AS (
-          SELECT
-            employees.*,
-            d.*,
-            dept_no
-          FROM
-            employees
-            JOIN department AS d USING(dept_no)
-          LIMIT
-            10
-        )
-        SELECT
-          table_0.emp_no,
-          table_0.name,
-          s.salary
-        FROM
-          table_0
-          JOIN salaries AS s USING(emp_no)
-        "###);
-
-        let prql = r###"
-        from e=employees
-        take 10
-        join salaries [emp_no]
-        select [e.*, salary]
-        "###;
-        let result = parse(prql).and_then(resolve_and_translate).unwrap();
-        assert_display_snapshot!(result, @r###"
-        WITH table_0 AS (
-          SELECT
-            e.*
-          FROM
-            employees AS e
-          LIMIT
-            10
-        )
-        SELECT
-          table_0.*,
-          salary
-        FROM
-          table_0
-          JOIN salaries USING(emp_no)
-        "###);
-    }
-
-    #[test]
-    fn test_table_alias() -> Result<()> {
-        // Alias on from
-        let query: Query = parse(
-            r###"
-            from e = employees
-            join salaries side:left [salaries.emp_no == e.emp_no]
-            group [e.emp_no] (
-                aggregate [
-                    emp_salary = average salary
-                ]
-            )
-            select [e.emp_no, emp_salary]
-        "###,
-        )?;
-
-        assert_display_snapshot!((resolve_and_translate(query)?), @r###"
-        SELECT
-          e.emp_no,
-          AVG(salary) AS emp_salary
-        FROM
-          employees AS e
-          LEFT JOIN salaries ON salaries.emp_no = e.emp_no
-        GROUP BY
-          e.emp_no
-        "###);
-        Ok(())
-    }
-
-    #[test]
-    fn test_dialects() -> Result<()> {
-        // Generic
-        let query: Query = parse(
-            r###"
-        prql dialect:generic
-        from Employees
-        select [FirstName, `last name`]
-        take 3
-        "###,
-        )?;
-
-        assert_display_snapshot!((resolve_and_translate(query)?), @r###"
-        SELECT
-          "FirstName",
-          "last name"
-        FROM
-          "Employees"
-        LIMIT
-          3
-        "###);
-
-        // SQL server
-        let query: Query = parse(
-            r###"
-        prql dialect:mssql
-        from Employees
-        select [FirstName, `last name`]
-        take 3
-        "###,
-        )?;
-
-        assert_display_snapshot!((resolve_and_translate(query)?), @r###"
-        SELECT
-          TOP (3) "FirstName",
-          "last name"
-        FROM
-          "Employees"
-        "###);
-
-        // MySQL
-        let query: Query = parse(
-            r###"
-        prql dialect:mysql
-        from Employees
-        select [FirstName, `last name`]
-        take 3
-        "###,
-        )?;
-
-        assert_display_snapshot!((resolve_and_translate(query)?), @r###"
-        SELECT
-          `FirstName`,
-          `last name`
-        FROM
-          `Employees`
-        LIMIT
-          3
-        "###);
-
-        Ok(())
-    }
-
-    #[test]
-    fn test_ident_escaping() -> Result<()> {
-        // Generic
-        let query: Query = parse(
-            r###"
-        from `anim"ls`
-        derive [`čebela` = BeeName, medved = `bear's_name`]
-        "###,
-        )?;
-
-        assert_display_snapshot!((resolve_and_translate(query)?), @r###"
-        SELECT
-          "anim""ls".*,
-          "BeeName" AS "čebela",
-          "bear's_name" AS medved
-        FROM
-          "anim""ls"
-        "###);
-
-        // MySQL
-        let query: Query = parse(
-            r###"
-        prql dialect:mysql
-
-        from `anim"ls`
-        derive [`čebela` = BeeName, medved = `bear's_name`]
-        "###,
-        )?;
-
-        assert_display_snapshot!((resolve_and_translate(query)?), @r###"
-        SELECT
-          `anim"ls`.*,
-          `BeeName` AS `čebela`,
-          `bear's_name` AS medved
-        FROM
-          `anim"ls`
-        "###);
-
-        Ok(())
-    }
-
-    #[test]
-    fn test_sorts() -> Result<()> {
-        let query: Query = parse(
-            r###"
-        from invoices
-        sort [issued_at, -amount, +num_of_articles]
-        "###,
-        )?;
-
-        assert_display_snapshot!((resolve_and_translate(query)?), @r###"
-        SELECT
-          invoices.*
-        FROM
-          invoices
-        ORDER BY
-          issued_at,
-          amount DESC,
-          num_of_articles
-        "###);
-
-        Ok(())
-    }
-
-    #[test]
-    fn test_ranges() -> Result<()> {
-        let query: Query = parse(
-            r###"
-        from employees
-        filter (age | in 18..40)
-        "###,
-        )?;
-
-        assert_display_snapshot!((resolve_and_translate(query)?), @r###"
-        SELECT
-          employees.*
-        FROM
-          employees
-        WHERE
-          age BETWEEN 18
-          AND 40
-        "###);
-
-        let query: Query = parse(
-            r###"
-        from employees
-        filter (age | in ..40)
-        "###,
-        )?;
-
-        assert!(resolve_and_translate(query).is_err());
-
-        let query: Query = parse(
-            r###"
-        from events
-        filter (date | in @1776-07-04..@1787-09-17)
-        "###,
-        )?;
-
-        assert_display_snapshot!((resolve_and_translate(query)?), @r###"
-        SELECT
-          events.*
-        FROM
-          events
-        WHERE
-          date BETWEEN DATE '1776-07-04'
-          AND DATE '1787-09-17'
-        "###);
-
-        Ok(())
-    }
-
-    #[test]
-    fn test_interval() -> Result<()> {
-        let query: Query = parse(
-            r###"
-        from projects
-        derive first_check_in = start + 10days
-        "###,
-        )?;
-
-        assert_display_snapshot!((resolve_and_translate(query)?), @r###"
-        SELECT
-          projects.*,
-          start + INTERVAL '10' DAY AS first_check_in
-        FROM
-          projects
-        "###);
-
-        Ok(())
-    }
-
-    #[test]
-    fn test_dates() -> Result<()> {
-        let query: Query = parse(
-            r###"
-        derive [
-            date = @2011-02-01,
-            timestamp = @2011-02-01T10:00,
-            time = @14:00,
-            # datetime = @2011-02-01T10:00<datetime>,
-        ]
-
-        "###,
-        )?;
-
-        assert_display_snapshot!((resolve_and_translate(query)?), @r###"
-        SELECT
-          DATE '2011-02-01' AS date,
-          TIMESTAMP '2011-02-01T10:00' AS timestamp,
-          TIME '14:00' AS time
-        "###);
-
-        Ok(())
-    }
-
-    #[test]
-    fn test_window_functions() {
-        let query: Query = parse(
-            r###"
-        from employees
-        group last_name (
-            derive count
-        )
-        "###,
-        )
-        .unwrap();
-
-        assert_display_snapshot!((resolve_and_translate(query).unwrap()), @r###"
-        SELECT
-          employees.*,
-          COUNT(*) OVER (PARTITION BY last_name)
-        FROM
-          employees
-        "###);
-
-        let query: Query = parse(
-            r###"
-        from co=cust_order
-        join ol=order_line [order_id]
-        derive [
-          order_month = s"TO_CHAR({co.order_date}, '%Y-%m')",
-          order_day = s"TO_CHAR({co.order_date}, '%Y-%m-%d')",
-        ]
-        group [order_month, order_day] (
-          aggregate [
-            num_orders = s"COUNT(DISTINCT {co.order_id})",
-            num_books = count non_null:ol.book_id,
-            total_price = sum ol.price,
-          ]
-        )
-        group [order_month] (
-          sort order_day
-          window expanding:true (
-            derive [running_total_num_books = sum num_books]
-          )
-        )
-        sort order_day
-        derive [num_books_last_week = lag 7 num_books]
-        "###,
-        )
-        .unwrap();
-
-        assert_display_snapshot!((resolve_and_translate(query).unwrap()), @r###"
-        SELECT
-          TO_CHAR(co.order_date, '%Y-%m') AS order_month,
-          TO_CHAR(co.order_date, '%Y-%m-%d') AS order_day,
-          COUNT(DISTINCT co.order_id) AS num_orders,
-          COUNT(ol.book_id) AS num_books,
-          SUM(ol.price) AS total_price,
-          SUM(COUNT(ol.book_id)) OVER (
-            PARTITION BY TO_CHAR(co.order_date, '%Y-%m')
-            ORDER BY
-              TO_CHAR(co.order_date, '%Y-%m-%d') ROWS BETWEEN UNBOUNDED PRECEDING
-              AND CURRENT ROW
-          ) AS running_total_num_books,
-          LAG(COUNT(ol.book_id), 7) OVER (
-            ORDER BY
-              TO_CHAR(co.order_date, '%Y-%m-%d') ROWS BETWEEN UNBOUNDED PRECEDING
-              AND UNBOUNDED FOLLOWING
-          ) AS num_books_last_week
-        FROM
-          cust_order AS co
-          JOIN order_line AS ol USING(order_id)
-        GROUP BY
-          TO_CHAR(co.order_date, '%Y-%m'),
-          TO_CHAR(co.order_date, '%Y-%m-%d')
-        ORDER BY
-          order_day
-        "###);
-
-        // lag must be recognized as window function, even outside of group context
-        // rank must not have two OVER clauses
-        let query: Query = parse(
-            r###"
-        from daily_orders
-        derive [last_week = lag 7 num_orders]
-        group month ( derive [total_month = sum num_orders])
-        "###,
-        )
-        .unwrap();
-
-        assert_display_snapshot!((resolve_and_translate(query).unwrap()), @r###"
-        SELECT
-          daily_orders.*,
-          LAG(num_orders, 7) OVER () AS last_week,
-          SUM(num_orders) OVER (PARTITION BY month) AS total_month
-        FROM
-          daily_orders
-        "###);
-
-        // sort does not affects into groups, group undoes sorting
-        let query: Query = parse(
-            r###"
-        from daily_orders
-        sort day
-        group month (derive [total_month = rank])
-        derive [last_week = lag 7 num_orders]
-        "###,
-        )
-        .unwrap();
-        assert_display_snapshot!((resolve_and_translate(query).unwrap()), @r###"
-        SELECT
-          daily_orders.*,
-          RANK() OVER (PARTITION BY month) AS total_month,
-          LAG(num_orders, 7) OVER () AS last_week
-        FROM
-          daily_orders
-        ORDER BY
-          day
-        "###);
-
-        // sort does not leak out of groups
-        let query: Query = parse(
-            r###"
-        from daily_orders
-        sort day
-        group month (sort num_orders | window expanding:true (derive rank))
-        derive [num_orders_last_week = lag 7 num_orders]
-        "###,
-        )
-        .unwrap();
-        assert_display_snapshot!((resolve_and_translate(query).unwrap()), @r###"
-        SELECT
-          daily_orders.*,
-          RANK() OVER (
-            PARTITION BY month
-            ORDER BY
-              num_orders ROWS BETWEEN UNBOUNDED PRECEDING
-              AND CURRENT ROW
-          ),
-          LAG(num_orders, 7) OVER () AS num_orders_last_week
-        FROM
-          daily_orders
-        "###);
-    }
-
-    #[test]
-    fn test_window_functions_2() {
-        // detect sum as a window function, even without group or window
-        assert_display_snapshot!((resolve_and_translate(parse(r###"
-        from foo
-        derive [a = sum b]
-        group c (
-            derive [d = sum b]
-        )
-        "###,
-        ).unwrap()).unwrap()), @r###"
-        SELECT
-          foo.*,
-          SUM(b) OVER () AS a,
-          SUM(b) OVER (PARTITION BY c) AS d
-        FROM
-          foo
-        "###);
-
-        assert_display_snapshot!((resolve_and_translate(parse(r###"
-        from foo
-        window expanding:true (
-            derive [running_total = sum b]
-        )
-        "###,
-        ).unwrap()).unwrap()), @r###"
-        SELECT
-          foo.*,
-          SUM(b) OVER (
-            ROWS BETWEEN UNBOUNDED PRECEDING
-            AND CURRENT ROW
-          ) AS running_total
-        FROM
-          foo
-        "###);
-
-        assert_display_snapshot!((resolve_and_translate(parse(r###"
-        from foo
-        window rolling:3 (
-            derive [last_three = sum b]
-        )
-        "###,
-        ).unwrap()).unwrap()), @r###"
-        SELECT
-          foo.*,
-          SUM(b) OVER (
-            ROWS BETWEEN 2 PRECEDING
-            AND CURRENT ROW
-          ) AS last_three
-        FROM
-          foo
-        "###);
-
-        assert_display_snapshot!((resolve_and_translate(parse(r###"
-        from foo
-        window rows:0..4 (
-            derive [next_four_rows = sum b]
-        )
-        "###,
-        ).unwrap()).unwrap()), @r###"
-        SELECT
-          foo.*,
-          SUM(b) OVER (
-            ROWS BETWEEN CURRENT ROW
-            AND 4 FOLLOWING
-          ) AS next_four_rows
-        FROM
-          foo
-        "###);
-
-        assert_display_snapshot!((resolve_and_translate(parse(r###"
-        from foo
-        sort day
-        window range:-4..4 (
-            derive [next_four_days = sum b]
-        )
-        "###,
-        ).unwrap()).unwrap()), @r###"
-        SELECT
-          foo.*,
-          SUM(b) OVER (
-            ORDER BY
-              day RANGE BETWEEN 4 PRECEDING
-              AND 4 FOLLOWING
-          ) AS next_four_days
-        FROM
-          foo
-        "###);
-
-        // TODO: add test for preceding
-    }
-
-    #[test]
-    fn test_strings() -> Result<()> {
-        let query: Query = parse(
-            r###"
-        derive [
-            x = "two households'",
-            y = 'two households"',
-            z = f"a {x} b' {y} c",
-            v = f'a {x} b" {y} c',
-        ]
-        "###,
-        )?;
-
-        assert_display_snapshot!((resolve_and_translate(query)?), @r###"
-        SELECT
-          'two households''' AS x,
-          'two households"' AS y,
-          CONCAT(
-            'a ',
-            'two households''',
-            ' b'' ',
-            'two households"',
-            ' c'
-          ) AS z,
-          CONCAT(
-            'a ',
-            'two households''',
-            ' b" ',
-            'two households"',
-            ' c'
-          ) AS v
-        "###);
-
-        Ok(())
-    }
-
-    #[test]
-    fn test_filter() {
-        // https://github.com/prql/prql/issues/469
-        let query: Query = parse(
-            r###"
-        from employees
-        filter [age > 25, age < 40]
-        "###,
-        )
-        .unwrap();
-
-        assert!(resolve_and_translate(query).is_err());
-
-        assert_display_snapshot!((resolve_and_translate(parse(r###"
-        from employees
-        filter age > 25 and age < 40
-        "###,
-        ).unwrap()).unwrap()), @r###"
-        SELECT
-          employees.*
-        FROM
-          employees
-        WHERE
-          age > 25
-          AND age < 40
-        "###);
-
-        assert_display_snapshot!((resolve_and_translate(parse(r###"
-        from employees
-        filter age > 25
-        filter age < 40
-        "###,
-        ).unwrap()).unwrap()), @r###"
-        SELECT
-          employees.*
-        FROM
-          employees
-        WHERE
-          age > 25
-          AND age < 40
-        "###);
-    }
-
-    #[test]
-    fn test_nulls() -> Result<()> {
-        assert_display_snapshot!((resolve_and_translate(parse(r###"
-        from employees
-        select amount = null
-        "###,
-        )?)?), @r###"
-        SELECT
-          NULL AS amount
-        FROM
-          employees
-        "###);
-
-        // coalesce
-        assert_display_snapshot!((resolve_and_translate(parse(r###"
-        from employees
-        derive amount = amount + 2 ?? 3 * 5
-        "###,
-        )?)?), @r###"
-        SELECT
-          employees.*,
-          COALESCE(amount + 2, 3 * 5) AS amount
-        FROM
-          employees
-        "###);
-
-        // IS NULL
-        assert_display_snapshot!((resolve_and_translate(parse(r###"
-        from employees
-        filter first_name == null and null == last_name
-        "###,
-        )?)?), @r###"
-        SELECT
-          employees.*
-        FROM
-          employees
-        WHERE
-          first_name IS NULL
-          AND last_name IS NULL
-        "###);
-
-        // IS NOT NULL
-        assert_display_snapshot!((resolve_and_translate(parse(r###"
-        from employees
-        filter first_name != null and null != last_name
-        "###,
-        )?)?), @r###"
-        SELECT
-          employees.*
-        FROM
-          employees
-        WHERE
-          first_name IS NOT NULL
-          AND last_name IS NOT NULL
-        "###);
-
-        Ok(())
-    }
-
-    #[test]
-    fn test_range() -> Result<()> {
-        assert_display_snapshot!((resolve_and_translate(parse(r###"
-        from employees
-        take ..10
-        "###,
-        )?)?), @r###"
-        SELECT
-          employees.*
-        FROM
-          employees
-        LIMIT
-          10
-        "###);
-
-        assert_display_snapshot!((resolve_and_translate(parse(r###"
-        from employees
-        take 5..10
-        "###,
-        )?)?), @r###"
-        SELECT
-          employees.*
-        FROM
-          employees
-        LIMIT
-          6 OFFSET 4
-        "###);
-
-        assert_display_snapshot!((resolve_and_translate(parse(r###"
-        from employees
-        take 5..
-        "###,
-        )?)?), @r###"
-        SELECT
-          employees.*
-        FROM
-          employees OFFSET 4
-        "###);
-
-        // should be one SELECT
-        assert_display_snapshot!((resolve_and_translate(parse(r###"
-        from employees
-        take 11..20
-        take 1..5
-        "###,
-        )?)?), @r###"
-        SELECT
-          employees.*
-        FROM
-          employees
-        LIMIT
-          5 OFFSET 10
-        "###);
-
-        // should be two SELECTs
-        assert_display_snapshot!((resolve_and_translate(parse(r###"
-        from employees
-        take 11..20
-        sort name
-        take 1..5
-        "###,
-        )?)?), @r###"
-        WITH table_0 AS (
-          SELECT
-            employees.*
-          FROM
-            employees
-          LIMIT
-            10 OFFSET 10
-        )
-        SELECT
-          table_0.*
-        FROM
-          table_0
-        ORDER BY
-          name
-        LIMIT
-          5
-        "###);
-
-        Ok(())
-    }
-
-    #[test]
-    fn test_distinct() {
-        // window functions cannot materialize into where statement: CTE is needed
-        assert_display_snapshot!((resolve_and_translate(parse(r###"
-        from employees
-        derive rn = row_number
-        filter rn > 2
-        "###,
-        ).unwrap()).unwrap()), @r###"
-        WITH table_0 AS (
-          SELECT
-            employees.*,
-            ROW_NUMBER() OVER () AS rn
-          FROM
-            employees
-        )
-        SELECT
-          table_0.*
-        FROM
-          table_0
-        WHERE
-          rn > 2
-        "###);
-
-        // basic distinct
-        assert_display_snapshot!((resolve_and_translate(parse(r###"
-        from employees
-        select first_name
-        group first_name (take 1)
-        "###,
-        ).unwrap()).unwrap()), @r###"
-        SELECT
-          DISTINCT first_name
-        FROM
-          employees
-        "###);
-
-        // distinct on two columns
-        assert_display_snapshot!((resolve_and_translate(parse(r###"
-        from employees
-        select [first_name, last_name]
-        group [first_name, last_name] (take 1)
-        "###,
-        ).unwrap()).unwrap()), @r###"
-        SELECT
-          DISTINCT first_name,
-          last_name
-        FROM
-          employees
-        "###);
-
-        // TODO: this should not use DISTINCT but ROW_NUMBER and WHERE, because we want
-        // row  distinct only over first_name and last_name.
-        assert_display_snapshot!((resolve_and_translate(parse(r###"
-        from employees
-        group [first_name, last_name] (take 1)
-        "###,
-        ).unwrap()).unwrap()), @r###"
-        SELECT
-          DISTINCT employees.*
-        FROM
-          employees
-        "###);
-
-        // head
-        assert_display_snapshot!((resolve_and_translate(parse(r###"
-        from employees
-        group department (take 3)
-        "###,
-        ).unwrap()).unwrap()), @r###"
-        WITH table_0 AS (
-          SELECT
-            employees.*,
-            ROW_NUMBER() OVER (PARTITION BY department) AS _rn_81
-          FROM
-            employees
-        )
-        SELECT
-          table_0.*
-        FROM
-          table_0
-        WHERE
-          _rn_81 <= 3
-        "###);
-
-        assert_display_snapshot!((resolve_and_translate(parse(r###"
-        from employees
-        group department (sort salary | take 2..3)
-        "###,
-        ).unwrap()).unwrap()), @r###"
-        WITH table_0 AS (
-          SELECT
-            employees.*,
-            ROW_NUMBER() OVER (
-              PARTITION BY department
-              ORDER BY
-                salary
-            ) AS _rn_82
-          FROM
-            employees
-        )
-        SELECT
-          table_0.*
-        FROM
-          table_0
-        WHERE
-          _rn_82 BETWEEN 2
-          AND 3
-        "###);
-    }
-
-    #[test]
-    fn test_dbt_query() {
-        assert_display_snapshot!((resolve_and_translate(parse(r###"
-        from {{ ref('stg_orders') }}
-        aggregate (min order_id)
-        "###,
-        ).unwrap()).unwrap()), @r###"
-        SELECT
-          MIN(order_id)
-        FROM
-          {{ ref('stg_orders') }}
-        "###);
-    }
-
-    #[test]
-    fn test_join() -> Result<()> {
-        assert_display_snapshot!((resolve_and_translate(parse(r###"
-        from x
-        join y [id]
-        "###,
-        )?)?), @r###"
-        SELECT
-          x.*,
-          y.*,
-          id
-        FROM
-          x
-          JOIN y USING(id)
-        "###);
-
-        // TODO: is there a better way to format the errors? `anyhow::Error`
-        // doesn't seem to serialize. We'd really like to show and test the
-        // error messages in our test suite.
-        assert_snapshot!((resolve_and_translate(parse(r###"
-        from x
-        join y [x.id]
-        "###,
-        )?).unwrap_err().to_string()), @r###"Error { span: None, reason: Expected { who: Some("join"), expected: "An identifer with only one part; no `.`", found: "A multipart identifer" }, help: None }"###);
-
-        Ok(())
-    }
-
-    #[test]
-    fn test_precedence() -> Result<()> {
-        assert_display_snapshot!((resolve_and_translate(parse(r###"
-        from x
-        derive [
-          n = a + b,
-          r = a/n,
-        ]
-        select temp_c = (temp - 32) * 3
-        "###,
-        )?)?), @r###"
-        SELECT
-          (temp - 32) * 3 AS temp_c
-        FROM
-          x
-        "###);
-
-        assert_display_snapshot!((resolve_and_translate(parse(r###"
-        func add a b -> a + b
-
-        from numbers
-        derive [sum_1 = a + b, sum_2 = add a b]
-        select [result = c * sum_1 + sum_2]
-        "###,
-        )?)?), @r###"
-        SELECT
-          c * (a + b) + a + b AS result
-        FROM
-          numbers
-        "###);
-
-        assert_display_snapshot!((resolve_and_translate(parse(r###"
-        from numbers
-        derive [g = -a]
-        select a * g
-        "###,
-        )?)?), @r###"
-        SELECT
-          a * - a
-        FROM
-          numbers
-        "###);
-
-        assert_display_snapshot!((resolve_and_translate(parse(r###"
-        from numbers
-        select negated_is_null = (!a) == null
-        "###,
-        )?)?), @r###"
-        SELECT
-          (NOT a) IS NULL AS negated_is_null
-        FROM
-          numbers
-        "###);
-
-        assert_display_snapshot!((resolve_and_translate(parse(r###"
-        from numbers
-        select is_not_null = !(a == null)
-        "###,
-        )?)?), @r###"
-        SELECT
-          NOT a IS NULL AS is_not_null
-        FROM
-          numbers
-        "###);
-
-        assert_display_snapshot!((resolve_and_translate(parse(r###"
-        from numbers
-        select (a + b) == null
-        "###
-        )?)?), @r###"
-        SELECT
-          a + b IS NULL
-        FROM
-          numbers
-        "###);
-
-        Ok(())
-    }
-
-    #[test]
-    fn test_pipelines() {
-        assert_display_snapshot!((resolve_and_translate(parse(r###"
-        from employees
-        group dept (take 1)
-        "###,
-        ).unwrap()).unwrap()), @r###"
-        SELECT
-          DISTINCT employees.*
-        FROM
-          employees
-        "###);
-    }
-
-    #[test]
-    fn test_rn_ids_are_unique() {
-        assert_display_snapshot!((resolve_and_translate(parse(r###"
-        from y_orig
-        group [y_id] (
-          take 2 # take 1 uses `distinct` instead of partitioning, which might be a separate bug
-        )
-        group [x_id] (
-          take 3
-        )
-        "###,
-        ).unwrap()).unwrap()), @r###"
-        WITH table_0 AS (
-          SELECT
-            y_orig.*,
-            ROW_NUMBER() OVER (PARTITION BY y_id) AS _rn_82
-          FROM
-            y_orig
-        ),
-        table_1 AS (
-          SELECT
-            table_0.*,
-            ROW_NUMBER() OVER (PARTITION BY x_id) AS _rn_83
-          FROM
-            table_0
-          WHERE
-            _rn_82 <= 2
-        )
-        SELECT
-          table_1.*
-        FROM
-          table_1
-        WHERE
-          _rn_83 <= 3
-        "###);
-    }
-
-    #[test]
-    fn test_quoting() -> Result<()> {
-        // #822
-        assert_display_snapshot!((resolve_and_translate(parse(r###"
-prql dialect:postgres
-from some_schema.tablename
-        "###,
-        )?)?), @r###"
-        SELECT
-          some_schema.tablename.*
-        FROM
-          some_schema.tablename
-        "###);
-
-        // #852
-        assert_display_snapshot!((resolve_and_translate(parse(r###"
-prql dialect:bigquery
-from db.schema.table
-join `db.schema.table2` [id]
-join `db`.`schema`.`table3` [id]
-join `db.schema.t-able` [id]
-        "###,
-        )?)?), @r###"
-        SELECT
-          `db.schema.table`.*,
-          `db.schema.table2`.*,
-          `db.schema.table3`.*,
-          `db.schema.t-able`.*,
-          id
-        FROM
-          `db.schema.table`
-          JOIN `db.schema.table2` USING(id)
-          JOIN `db.schema.table3` USING(id)
-          JOIN `db.schema.t-able` USING(id)
-        "###);
-
-        assert_display_snapshot!((resolve_and_translate(parse(r###"
-from table
-select `first name`
-        "###,
-        )?)?), @r###"
-        SELECT
-          "first name"
-        FROM
-          table
-        "###);
-
         Ok(())
     }
 }


Test patch:
diff --git a/prql-compiler/src/sql/snapshots/prql_compiler__sql__translator__test__prql_to_sql_2.snap b/prql-compiler/src/snapshots/prql_compiler__test__prql_to_sql_2.snap
similarity index 90%
rename from prql-compiler/src/sql/snapshots/prql_compiler__sql__translator__test__prql_to_sql_2.snap
rename to prql-compiler/src/snapshots/prql_compiler__test__prql_to_sql_2.snap
index e3f29634..7c8c1b01 100644
--- a/prql-compiler/src/sql/snapshots/prql_compiler__sql__translator__test__prql_to_sql_2.snap
+++ b/prql-compiler/src/snapshots/prql_compiler__test__prql_to_sql_2.snap
@@ -1,5 +1,5 @@
 ---
-source: prql-compiler/src/sql/translator.rs
+source: prql-compiler/src/lib.rs
 expression: sql
 ---
 SELECT