==================
Select 1
==================

SELECT 1;

---

(program
 (statement
  (select
   (keyword_select)
   (select_expression
    (literal)))))

==================
Select aliased literals
==================

SELECT 1 AS one,
  TRUE AS two,
  NULL AS three;

---

(program
 (statement
  (select
   (keyword_select)
   (select_expression
    (literal) (keyword_as) (identifier)
    (literal (keyword_true)) (keyword_as) (identifier)
    (literal (keyword_null)) (keyword_as) (identifier)))))

==================
Simple select
==================

SELECT * FROM my_table;

---

(program
 (statement
  (select
   (keyword_select)
   (select_expression (all_fields)))
  (from
   (keyword_from)
   (table_expression name: (identifier)))))

==================
Table.*
==================

SELECT my_table.* FROM my_table;

---

(program
 (statement
  (select
   (keyword_select)
   (select_expression
     (all_fields table_alias: (identifier))))
  (from
   (keyword_from)
   (table_expression name: (identifier)))))

==================
Alias.*
==================

SELECT t.* FROM my_table AS t;

---

(program
 (statement
  (select
   (keyword_select)
   (select_expression
     (all_fields table_alias: (identifier))))
  (from
   (keyword_from)
   (table_expression
     name: (identifier)
     (keyword_as)
     table_alias: (identifier)))))

==================
Simple select with fields
==================

SELECT id, name FROM my_table;

---

(program
 (statement
  (select
   (keyword_select)
   (select_expression
    (field name: (identifier))
    (field name: (identifier))))
  (from
   (keyword_from)
   (table_expression name: (identifier)))))

==================
Simple select with fields that look like keywords
==================

SELECT t.from_where, t.created_at, t.updated_at
FROM join_something_on AS where_this_like_that;

---

(program
 (statement
  (select
   (keyword_select)
   (select_expression
    (field table_alias: (identifier) name: (identifier))
    (field table_alias: (identifier) name: (identifier))
    (field table_alias: (identifier) name: (identifier))))
  (from
   (keyword_from)
   (table_expression name: (identifier) (keyword_as) table_alias: (identifier)))))

==================
Simple select with fields field table alias
==================

SELECT m.id, m.name
FROM my_table m;

---

(program
  (statement
    (select
     (keyword_select)
     (select_expression
      (field
       table_alias: (identifier)
       name: (identifier))
      (field
       table_alias: (identifier)
       name: (identifier))))
    (from
     (keyword_from)
     (table_expression
      name: (identifier)
      table_alias: (identifier)))))

==================
Simple select with where
==================

SELECT id
FROM my_table
WHERE id = 4;

---

(program
 (statement
  (select
   (keyword_select)
   (select_expression
    (field
     name: (identifier))))
  (from
   (keyword_from)
   (table_expression
    name: (identifier))
   (where
    (keyword_where)
    (where_expression
     (predicate
      left: (field name: (identifier))
      right: (literal)))))))

==================
Simple select with where and string
==================

SELECT id
FROM my_table
WHERE id = "abc";

---

(program
 (statement
  (select
   (keyword_select)
   (select_expression
    (field
     name: (identifier))))
  (from
   (keyword_from)
   (table_expression
    name: (identifier))
   (where
    (keyword_where)
    (where_expression
     (predicate
      left: (field name: (identifier))
      right: (literal)))))))

==================
Simple select with IN
==================

SELECT id
FROM my_table
WHERE id IN(1,2);

---

(program
 (statement
  (select
   (keyword_select)
   (select_expression
    (field
     name: (identifier))))
  (from
   (keyword_from)
   (table_expression
    name: (identifier))
   (where
    (keyword_where)
    (where_expression
     (predicate
      left: (field name: (identifier))
      operator: (keyword_in)
      right: (list (literal) (literal))))))))

==================
Simple select with IF
==================

SELECT IF(m.is_published, 'global', 'local') as published_scope
FROM my_table m;

---

(program
 (statement
  (select
   (keyword_select)
   (select_expression
    (function_call
      (invocation
        name: (identifier)
        parameter: (field
          table_alias: (identifier)
          name: (identifier))
        parameter: (literal)
        parameter: (literal)))
      (keyword_as)
      alias: (identifier)))
  (from
   (keyword_from)
   (table_expression
    name: (identifier)
    table_alias: (identifier)))))

==================
Select with complex IF
==================

SELECT m.is_published, IF(m.is_published > 4, 'global', 'local') published_scope
FROM my_table m;

---

(program
 (statement
  (select
   (keyword_select)
   (select_expression
    (field table_alias: (identifier) name: (identifier))
    (function_call
      (invocation
        name: (identifier)
        parameter: (predicate
         left: (field
          table_alias: (identifier)
          name: (identifier))
         right: (literal))
        parameter: (literal)
        parameter: (literal)))
      alias: (identifier)))
  (from
   (keyword_from)
   (table_expression
    name: (identifier)
    table_alias: (identifier)))))

==================
Select with distinct without parenthesis
==================

SELECT DISTINCT id
FROM my_table;

---

(program
 (statement
  (select
   (keyword_select)
   (keyword_distinct)
   (select_expression
    (field
     name: (identifier))))
  (from
   (keyword_from)
   (table_expression
    name: (identifier)))))

==================
Select with count and distinct without parenthesis and alias
==================

SELECT COUNT(DISTINCT id) AS count
FROM my_table;

---

(program
 (statement
  (select
   (keyword_select)
   (select_expression
    (function_call
     name: (identifier)
     (keyword_distinct)
     parameter: (field
      name: (identifier)))
    (keyword_as)
    alias: (identifier)))
  (from
   (keyword_from)
   (table_expression
    name: (identifier)))))

==================
Simple select with AS
==================

SELECT m.id AS m_id, m.a_id a_id
FROM my_table AS m;

---

(program
 (statement
  (select
   (keyword_select)
   (select_expression
    (field
     table_alias: (identifier)
     name: (identifier))
    (keyword_as)
    alias: (identifier)
    (field
     table_alias: (identifier)
     name: (identifier))
    alias: (identifier)))
  (from
   (keyword_from)
   (table_expression
    name: (identifier)
    (keyword_as)
    table_alias: (identifier)))))

==================
Simple select with order by
==================

SELECT id
FROM my_table
WHERE id > 4
ORDER BY id DESC;

---

(program
 (statement
  (select
   (keyword_select)
   (select_expression
    (field
     name: (identifier))))
  (from
   (keyword_from)
   (table_expression
    name: (identifier))
   (where
    (keyword_where)
    (where_expression
     (predicate
      left: (field name: (identifier))
      right: (literal))))
   (order_by
    (keyword_order_by)
    (order_expression
     (field name: (identifier))
     (direction (keyword_desc)))))))

==================
Simple select with limit
==================

SELECT id
FROM my_table
LIMIT 5;

---

(program
 (statement
  (select
   (keyword_select)
   (select_expression
    (field
     name: (identifier))))
  (from
   (keyword_from)
   (table_expression
    name: (identifier))
   (limit
    (keyword_limit)
    (literal)))))

==================
Simple select with offset
==================

SELECT id
FROM my_table
LIMIT 5
OFFSET 40;

---

(program
 (statement
  (select
   (keyword_select)
   (select_expression
    (field
     name: (identifier))))
  (from
   (keyword_from)
   (table_expression
    name: (identifier))
   (limit
    (keyword_limit)
    (literal)
    (offset
     (keyword_offset)
     (literal))))))

==================
Simple select with schema
==================

SELECT * FROM my_schema.my_table;

---

(program
 (statement
  (select
   (keyword_select)
   (select_expression (all_fields)))
  (from
   (keyword_from)
   (table_expression schema: (identifier) name: (identifier)))))

==================
Simple select with schema and fully-pathed fields
==================

SELECT my_schema.my_table.my_field FROM my_schema.my_table;

---

(program
 (statement
  (select
   (keyword_select)
   (select_expression (field schema: (identifier) table_alias: (identifier) name: (identifier))))
  (from
   (keyword_from)
   (table_expression schema: (identifier) name: (identifier)))))

==================
IS DISTINCT FROM
==================

SELECT *
FROM my_table
WHERE col IS DISTINCT FROM NULL;

---

(program
 (statement
  (select
   (keyword_select)
   (select_expression
    (all_fields)))
  (from
   (keyword_from)
   (table_expression
    (identifier))
   (where
    (keyword_where)
    (where_expression
     (predicate
      (field
       (identifier))
      (keyword_is)
      (keyword_distinct)
      (keyword_from)
      (literal
       (keyword_null))))))))

==================
IS NOT DISTINCT FROM
==================

SELECT *
FROM my_table
WHERE col IS NOT DISTINCT FROM NULL;

---

(program
 (statement
  (select
   (keyword_select)
   (select_expression
    (all_fields)))
  (from
   (keyword_from)
   (table_expression
    (identifier))
   (where
    (keyword_where)
    (where_expression
     (predicate
      (field
       (identifier))
      (keyword_is)
      (keyword_not)
      (keyword_distinct)
      (keyword_from)
      (literal
       (keyword_null))))))))

==================
Distinct
==================

SELECT DISTINCT(id)
FROM my_table;
---

(program
 (statement
  (select
   (keyword_select)
   (keyword_distinct)
   (select_expression
    (list
     (field
      name: (identifier)))))
  (from
   (keyword_from)
   (table_expression
    name: (identifier)))))

==================
Distinct, no extra parens
==================

SELECT DISTINCT id
FROM my_table;
---

(program
 (statement
  (select
   (keyword_select)
   (keyword_distinct)
   (select_expression
    (field
     name: (identifier))))
  (from
   (keyword_from)
   (table_expression
    name: (identifier)))))

==================
Functions
==================

SELECT MAX(id)
FROM my_table;
---

(program
 (statement
  (select
   (keyword_select)
   (select_expression
    (function_call
      (invocation
        name: (identifier)
        parameter: (field name: (identifier))))))
  (from
   (keyword_from)
   (table_expression
    name: (identifier)))))

==================
No-arg functions
==================

SELECT now();
---

(program
 (statement
  (select
   (keyword_select)
   (select_expression
    (function_call
      (invocation
        name: (identifier)))))))

==================
More complex function arguments
==================

SELECT
  user_id,
  user_defined_func(user_id, 123, other_func(user_id, 321), user_id + 1 > 5) as something,
  regexp_replace(t.username, '^(.)[^@]+', '\1--', 'g') as username,
  created_at
FROM my_table AS t;
---

(program
 (statement
  (select
   (keyword_select)
   (select_expression
    (field name: (identifier))
    (function_call
     (invocation
      name: (identifier)
      parameter: (field name: (identifier))
      parameter: (literal)
      parameter:
       (function_call
        (invocation
         name: (identifier)
         parameter: (field name: (identifier))
         parameter: (literal)))
      parameter:
       (predicate
        left: (binary_expression left: (field name: (identifier)) right: (literal))
        right: (literal))))
    (keyword_as) alias: (identifier)
    (function_call
     (invocation
      name: (identifier)
      parameter: (field table_alias: (identifier) name: (identifier))
      parameter: (literal)
      parameter: (literal)
      parameter: (literal)))
    (keyword_as) alias: (identifier)
    (field name: (identifier))))
  (from
   (keyword_from)
   (table_expression
    name: (identifier) (keyword_as) table_alias: (identifier)))))

==================
Distinct in count function
==================

SELECT COUNT(DISTINCT(id))
FROM my_table;
---

(program
 (statement
  (select
   (keyword_select)
   (select_expression
    (function_call
     name: (identifier)
     (keyword_distinct)
     parameter: (list
       (field
        name: (identifier))))))
  (from
   (keyword_from)
   (table_expression
    name: (identifier)))))

==================
Distinct in count function, no extra parens
==================

SELECT COUNT(DISTINCT id)
FROM my_table;
---

(program
 (statement
  (select
   (keyword_select)
   (select_expression
    (function_call
     name: (identifier)
     (keyword_distinct)
     parameter:
     (field
      name: (identifier)))))
  (from
   (keyword_from)
   (table_expression
    name: (identifier)))))

==================
Group by
==================

SELECT other_id, COUNT(name)
FROM my_table
GROUP BY other_id
HAVING other_id > 10;
---

(program
 (statement
  (select
   (keyword_select)
   (select_expression
    (field name: (identifier))
    (function_call
     name: (identifier)
     parameter: (field name: (identifier)))))
  (from
   (keyword_from)
   (table_expression
    name: (identifier))
   (group_by
    (keyword_group_by)
    (identifier)
    (keyword_having)
    (predicate
     left: (field name: (identifier))
     right: (literal))))))

==================
Joins
==================

SELECT a.id, b.id
FROM my_table a
JOIN my_other_table b
ON a.id = b.a_id
WHERE b.c_id = 4;

---

(program
 (statement
  (select
   (keyword_select)
   (select_expression
    (field
     table_alias: (identifier)
     name: (identifier))
    (field
     table_alias: (identifier)
     name: (identifier))))
  (from
   (keyword_from)
   (table_expression
    name: (identifier)
    table_alias: (identifier))
   (join
    (keyword_join)
    (table_expression
     name: (identifier)
     table_alias: (identifier))
    (keyword_on)
    (predicate
     left: (field
      table_alias: (identifier)
      name: (identifier))
     right: (field
      table_alias: (identifier)
      name: (identifier))))
   (where
    (keyword_where)
    (where_expression
     (predicate
      left: (field
       table_alias: (identifier)
       name: (identifier))
      right: (literal)))))))

==================
Join with boolean
==================

SELECT *
FROM my_table
JOIN my_other_table ON TRUE;

---

(program
 (statement
  (select
   (keyword_select)
   (select_expression (all_fields)))
  (from
   (keyword_from)
   (table_expression
    name: (identifier))
   (join
    (keyword_join)
    (table_expression
     name: (identifier))
    (keyword_on)
    (keyword_true))
   )))

==================
Joins with hint
==================

SELECT a.id, b.id
FROM my_table a
JOIN my_other_table b USE INDEX FOR JOIN (idx_a)
ON a.id = b.a_id;

---

(program
 (statement
  (select
   (keyword_select)
   (select_expression
    (field
     table_alias: (identifier)
     name: (identifier))
    (field
     table_alias: (identifier)
     name: (identifier))))
  (from
   (keyword_from)
   (table_expression
    name: (identifier)
    table_alias: (identifier))
   (join
    (keyword_join)
    (table_expression
     name: (identifier)
     table_alias: (identifier))
    (index_hint
     (keyword_use)
     (keyword_index)
     (keyword_for)
     (keyword_join)
     index_name: (identifier))
    (keyword_on)
    (predicate
     left: (field
      table_alias: (identifier)
      name: (identifier))
     right: (field
      table_alias: (identifier)
      name: (identifier)))))))

==================
Joins with USING
==================

SELECT a.id, b.id
FROM my_table a
JOIN my_other_table b USING (q, w);

---

(program
 (statement
  (select
   (keyword_select)
   (select_expression
    (field
     table_alias: (identifier)
     name: (identifier))
    (field
     table_alias: (identifier)
     name: (identifier))))
  (from
   (keyword_from)
   (table_expression
    name: (identifier)
    table_alias: (identifier))
   (join
    (keyword_join)
    (table_expression
     name: (identifier)
     table_alias: (identifier))
     (keyword_using)
     (column_list
       (column name: (identifier))
       (column name: (identifier))))
    )))

==================
Specific Joins
==================

SELECT table_a.id
FROM table_a a
LEFT JOIN table_b b
ON a.id = b.a_id
LEFT OUTER JOIN table_c c
ON a.id = c.a_id
RIGHT JOIN table_d d
ON a.id = d.d_id
RIGHT OUTER JOIN table_d d
ON a.id = d.d_id
INNER JOIN table_e e
ON a.id = e.e_id;

---

(program
 (statement
  (select
   (keyword_select)
   (select_expression
    (field
     table_alias: (identifier)
     name: (identifier))))
  (from
   (keyword_from)
   (table_expression
    name: (identifier)
    table_alias: (identifier))
   (join
    (keyword_left)
    (keyword_join)
    (table_expression
     name: (identifier)
     table_alias: (identifier))
    (keyword_on)
    (predicate
     left: (field
      table_alias: (identifier)
      name: (identifier))
     right: (field
      table_alias: (identifier)
      name: (identifier))))
   (join
    (keyword_left)
    (keyword_outer)
    (keyword_join)
    (table_expression
     name: (identifier)
     table_alias: (identifier))
    (keyword_on)
    (predicate
     left: (field
      table_alias: (identifier)
      name: (identifier))
     right: (field
      table_alias: (identifier)
      name: (identifier))))
   (join
    (keyword_right)
    (keyword_join)
    (table_expression
     name: (identifier)
     table_alias: (identifier))
    (keyword_on)
    (predicate
     left: (field
      table_alias: (identifier)
      name: (identifier))
     right: (field
      table_alias: (identifier)
      name: (identifier))))
   (join
    (keyword_right)
    (keyword_outer)
    (keyword_join)
    (table_expression
     name: (identifier)
     table_alias: (identifier))
    (keyword_on)
    (predicate
     left: (field
      table_alias: (identifier)
      name: (identifier))
     right: (field
      table_alias: (identifier)
      name: (identifier))))
   (join
    (keyword_inner)
    (keyword_join)
    (table_expression
     name: (identifier)
     table_alias: (identifier))
    (keyword_on)
    (predicate
     left: (field
      table_alias: (identifier)
      name: (identifier))
     right: (field
      table_alias: (identifier)
      name: (identifier)))))))

==================
Lateral join
==================

SELECT a.id, arr.*
FROM my_table a
JOIN LATERAL unnest(a.arr) AS arr ON TRUE;

---

(program
 (statement
  (select
   (keyword_select)
   (select_expression
    (field
     table_alias: (identifier)
     name: (identifier))
    (all_fields
     table_alias: (identifier))))
  (from
   (keyword_from)
   (table_expression
    name: (identifier)
    table_alias: (identifier))
   (lateral_join
    (keyword_join)
    (keyword_lateral)
    (invocation
      name: (identifier)
      parameter: (field
        table_alias: (identifier)
        name: (identifier)))
    (keyword_as)
    alias: (identifier)
    (keyword_on)
    (keyword_true)))))

==================
Lateral join subquery
==================

SELECT a.id, b.*
FROM my_table a
CROSS JOIN LATERAL (SELECT 1) AS b ON TRUE;

---

(program
 (statement
  (select
   (keyword_select)
   (select_expression
    (field
     table_alias: (identifier)
     name: (identifier))
    (all_fields
     table_alias: (identifier))))
  (from
   (keyword_from)
   (table_expression
    name: (identifier)
    table_alias: (identifier))
   (lateral_join
    (keyword_cross)
    (keyword_join)
    (keyword_lateral)
    (subquery
      (select
        (keyword_select)
        (select_expression (literal))))
    (keyword_as)
    alias: (identifier)
    (keyword_on)
    (keyword_true)))))

==================
Multiple joins
==================

SELECT a.id, b.id, c.id
FROM my_table a
JOIN my_other_table b
ON a.id = b.a_id
JOIN table_three c
ON a.id = c.a_id;

---

(program
 (statement
  (select
   (keyword_select)
   (select_expression
    (field
     table_alias: (identifier)
     name: (identifier))
    (field
     table_alias: (identifier)
     name: (identifier))
    (field
     table_alias: (identifier)
     name: (identifier))))
  (from
   (keyword_from)
   (table_expression
    name: (identifier)
    table_alias: (identifier))
   (join
    (keyword_join)
    (table_expression
     name: (identifier)
     table_alias: (identifier))
    (keyword_on)
    (predicate
     left: (field
      table_alias: (identifier)
      name: (identifier))
     right: (field
      table_alias: (identifier)
      name: (identifier))))
   (join
    (keyword_join)
    (table_expression
     name: (identifier)
     table_alias: (identifier))
    (keyword_on)
    (predicate
     left: (field
      table_alias: (identifier)
      name: (identifier))
     right: (field
      table_alias: (identifier)
      name: (identifier)))))))

==================
Complex Predicates
==================

SELECT id
FROM my_table m
WHERE m.id > 4 AND id < 3;

---

(program
 (statement
  (select
   (keyword_select)
   (select_expression
    (field
     name: (identifier))))
  (from
   (keyword_from)
   (table_expression
    name: (identifier)
    table_alias: (identifier))
   (where
    (keyword_where)
    (where_expression
     (predicate
      left:
       (predicate
        left:
          (field
           table_alias: (identifier)
           name: (identifier))
        right: (literal))
       operator: (keyword_and)
       right:
        (predicate
          left: (field name: (identifier))
          right: (literal))))))))

==================
Complex Predicates with order by
==================

SELECT title, id
FROM my_table m
WHERE m.id > 4 AND id < 3
ORDER BY m.title, id ASC;

---

(program
 (statement
  (select
   (keyword_select)
   (select_expression
    (field name: (identifier))
    (field name: (identifier))))
  (from
   (keyword_from)
   (table_expression
    name: (identifier)
    table_alias: (identifier))
   (where
    (keyword_where)
    (where_expression
     (predicate
      left:
       (predicate
        left:
          (field
           table_alias: (identifier)
           name: (identifier))
        right: (literal))
       operator: (keyword_and)
       right:
        (predicate
          left: (field name: (identifier))
          right: (literal)))))
   (order_by
    (keyword_order_by)
    (order_expression
     (field table_alias: (identifier) name: (identifier))
     (field name: (identifier))
     (direction (keyword_asc)))))))



==================
Index hints
==================

SELECT id
FROM my_table FORCE INDEX (long_index_identifier)
LIMIT 1;

---

(program
 (statement
  (select
   (keyword_select)
   (select_expression
    (field
     name: (identifier))))
  (from
   (keyword_from)
   (table_expression
    name: (identifier))
   (index_hint
    (keyword_force)
    (keyword_index)
    index_name: (identifier))
   (limit
    (keyword_limit)
    (literal)))))

==================
Index hints (use)
==================

SELECT id
FROM my_table USE INDEX (long_index_identifier)
LIMIT 1;

---

(program
 (statement
  (select
   (keyword_select)
   (select_expression
    (field
     name: (identifier))))
  (from
   (keyword_from)
   (table_expression
    name: (identifier))
   (index_hint
    (keyword_use)
    (keyword_index)
    index_name: (identifier))
   (limit
    (keyword_limit)
    (literal)))))

==================
Union
==================

SELECT 1 UNION ALL SELECT 2;

---

(program
 (statement
  (select
   (keyword_select)
   (select_expression
    (literal)))
   (keyword_union)
   (keyword_all)
  (select
   (keyword_select)
   (select_expression
    (literal)))))

==================
Intersect
==================

SELECT a FROM one
INTERSECT
SELECT b FROM two;

---

(program
 (statement
  (select
   (keyword_select)
   (select_expression
    (field (identifier))))
  (from
   (keyword_from)
   (table_expression (identifier)))
  (keyword_intersect)
  (select
   (keyword_select)
   (select_expression
    (field (identifier))))
  (from
   (keyword_from)
   (table_expression (identifier)))))

==================
Simple CASE
==================

SELECT a, CASE b WHEN 1 THEN 'yes' ELSE 'no' END AS is_b
FROM my_table;

---

(program
 (statement
  (select
   (keyword_select)
   (select_expression
    (field
     (identifier))
    (case
     (keyword_case)
     (field
      (identifier))
     (keyword_when)
     (literal)
     (keyword_then)
     (literal)
     (keyword_else)
     (literal)
     (keyword_end))
     (keyword_as)
     (identifier)))
  (from
   (keyword_from)
   (table_expression
    (identifier)))))

==================
Standard CASE
==================

SELECT a, CASE WHEN b = 1 THEN 'yes' ELSE 'no' END AS is_b
FROM my_table;

---

(program
 (statement
  (select
   (keyword_select)
   (select_expression
    (field
     (identifier))
    (case
     (keyword_case)
     (keyword_when)
     (predicate
      (field
       (identifier))
      (literal))
     (keyword_then)
     (literal)
     (keyword_else)
     (literal)
     (keyword_end))
    (keyword_as)
    (identifier)))
  (from
   (keyword_from)
   (table_expression
    (identifier)))))

==================
Both CASEs, with missing ELSE and AS in the latter
==================

SELECT a, CASE
    WHEN b = 1 THEN 'yes'
    WHEN b = 2 THEN 'maybe'
    ELSE 'no'
  END AS is_b,
  CASE b
    WHEN 1 THEN 'yes'
    WHEN 2 THEN 'maybe'
  END is_b_really
FROM my_table;

---

(program
 (statement
  (select
   (keyword_select)
   (select_expression
    (field
     (identifier))
    (case
     (keyword_case)
     (keyword_when)
     (predicate
      (field
       (identifier))
      (literal))
     (keyword_then)
     (literal)
     (keyword_when)
     (predicate
      (field
       (identifier))
      (literal))
     (keyword_then)
     (literal)
     (keyword_else)
     (literal)
     (keyword_end))
     (keyword_as)
     (identifier)
  (case
   (keyword_case)
   (field
    (identifier))
   (keyword_when)
   (literal)
   (keyword_then)
   (literal)
   (keyword_when)
   (literal)
   (keyword_then)
   (literal)
   (keyword_end))
   (identifier)))
  (from
   (keyword_from)
   (table_expression
    (identifier)))))

==================
Concatenation
==================

SELECT id || '-' || name FROM my_table;

---

(program
 (statement
  (select
   (keyword_select)
   (select_expression
    (binary_expression
     left: (binary_expression
      left: (field name: (identifier))
      right: (literal))
     right: (field name: (identifier)))))
  (from
   (keyword_from)
   (table_expression name: (identifier)))))

==================
Altogether now
==================

SELECT c._id, c.p_id
  FROM c_table c
FORCE INDEX (idx_c_on_s_id_and_p_id_and_c_id)
JOIN cp_table cp
  ON cp.c_id = c.id
  AND cp.s_id = c.s_id
JOIN my_table USE INDEX FOR JOIN (idx_my_table_on_s_id_and_id)
  ON c.c_id = my_table.id
  AND c.s_id = my_table.s_id
WHERE c.s_id = 1239
  AND c.p_id in (1)
  AND cp.ch_id = 6
  AND cp.is_published = TRUE
ORDER BY my_table.title, my_table.id;

----

(program
 (statement
  (select
   (keyword_select)
   (select_expression
    (field table_alias: (identifier) name: (identifier))
    (field table_alias: (identifier) name: (identifier))))
  (from
   (keyword_from)
   (table_expression
    name: (identifier)
    table_alias: (identifier))
   (index_hint
    (keyword_force)
    (keyword_index)
    index_name: (identifier))
   (join
    (keyword_join)
    (table_expression name: (identifier) table_alias: (identifier))
    (keyword_on)
    (predicate
     left:
     (predicate
      left: (field table_alias: (identifier) name: (identifier))
      right: (field table_alias: (identifier) name: (identifier)))
     operator: (keyword_and)
     right:
     (predicate
      left: (field table_alias: (identifier) name: (identifier))
      right: (field table_alias: (identifier) name: (identifier)))))
  (join
   (keyword_join)
   (table_expression name: (identifier))
   (index_hint
    (keyword_use)
    (keyword_index)
    (keyword_for)
    (keyword_join)
    index_name: (identifier))
   (keyword_on)
   (predicate
    left:
    (predicate
     left: (field table_alias: (identifier) name: (identifier))
     right: (field table_alias: (identifier) name: (identifier)))
    operator: (keyword_and)
    right:
    (predicate
     left: (field table_alias: (identifier) name: (identifier))
     right: (field table_alias: (identifier) name: (identifier)))))
  (where
   (keyword_where)
   (where_expression
    (predicate
     left:
     (predicate
      left:
      (predicate
       left:
       (predicate
        left:
        (field
         table_alias: (identifier)
         name: (identifier))
        right: (literal))
       operator: (keyword_and)
       right:
       (predicate
        left: (field table_alias: (identifier) name: (identifier))
        operator: (keyword_in)
        right: (list (literal))))
      operator: (keyword_and)
      right:
      (predicate
       left: (field table_alias: (identifier) name: (identifier))
       right: (literal)))
     operator: (keyword_and)
     right:
     (predicate
      left: (field table_alias: (identifier) name: (identifier))
      right: (literal (keyword_true))))))
  (order_by
   (keyword_order_by)
   (order_expression
    (field table_alias: (identifier) name: (identifier))
    (field table_alias: (identifier) name: (identifier)))))))
