Skip to content

Commit

Permalink
work on common commands in statements
Browse files Browse the repository at this point in the history
  • Loading branch information
inoas committed Apr 29, 2024
1 parent 9648f4c commit 22c612d
Show file tree
Hide file tree
Showing 4 changed files with 94 additions and 68 deletions.
2 changes: 1 addition & 1 deletion src/cake.gleam
Original file line number Diff line number Diff line change
Expand Up @@ -90,7 +90,7 @@ pub fn run_dummy_union_all() {
// |> query.select_query_order_asc("name")

let union_query =
query.union_all_query_new([select_query_a, select_query_b])
query.union_except_query_new([select_query_a, select_query_b])
// |> query.union_set_limit(1)
|> query.query_union_wrap
|> iox.dbg
Expand Down
130 changes: 81 additions & 49 deletions src/cake/internal/query.gleam
Original file line number Diff line number Diff line change
@@ -1,8 +1,5 @@
import cake/stdlib/iox

type EpilogPart =
String

// —————————————————————————————————————————————————————————————————————————— //
// ———— Query ——————————————————————————————————————————————————————————————— //
// —————————————————————————————————————————————————————————————————————————— //
Expand All @@ -25,85 +22,90 @@ pub fn query_union_wrap(qry: UnionQuery) -> Query {
// —————————————————————————————————————————————————————————————————————————— //

pub type UnionKind {
All
Distinct
Except
Intersect
UnionAll
UnionDistinct
UnionExcept
UnionIntersect
}

// List of SQL parts that will be used to build a union query.
pub type UnionQuery {
// unify and have a kind key that is All or Distinct
UnionDistinctQuery(
select_queries: List(SelectQuery),
limit_offset: LimitOffsetPart,
// Epilog allows you to append raw SQL to the end of queries.
// You should never put raw user data into epilog.
epilog: EpilogPart,
)
UnionAllQuery(
UnionQuery(
union_kind: UnionKind,
select_queries: List(SelectQuery),
limit_offset: LimitOffsetPart,
// order_by: List(OrderByPart),
// Epilog allows you to append raw SQL to the end of queries.
// You should never put raw user data into epilog.
epilog: EpilogPart,
)
// TODO: also takes order_by, limit, offset
// TODO: order_by of contained selects must be stripped
}

pub fn union_distinct_query_new(
select_queries slct_qrys: List(SelectQuery),
) -> UnionQuery {
UnionDistinctQuery(
UnionQuery(
union_kind: UnionDistinct,
select_queries: slct_qrys,
limit_offset: NoLimitOffset,
epilog: "",
epilog: NoEpilogPart,
)
}

pub fn union_all_query_new(
select_queries slct_qrys: List(SelectQuery),
) -> UnionQuery {
UnionAllQuery(
UnionQuery(
union_kind: UnionAll,
select_queries: slct_qrys,
limit_offset: NoLimitOffset,
epilog: "",
epilog: NoEpilogPart,
)
}

pub fn union_except_query_new(
select_queries slct_qrys: List(SelectQuery),
) -> UnionQuery {
UnionQuery(
union_kind: UnionExcept,
select_queries: slct_qrys,
limit_offset: NoLimitOffset,
epilog: NoEpilogPart,
)
}

pub fn union_intersect_query_new(
select_queries slct_qrys: List(SelectQuery),
) -> UnionQuery {
UnionQuery(
union_kind: UnionIntersect,
select_queries: slct_qrys,
limit_offset: NoLimitOffset,
epilog: NoEpilogPart,
)
}

pub fn union_get_select_queries(union_query uq: UnionQuery) -> List(SelectQuery) {
case uq {
// TODO: UNION vs UNION ALL vs EXCEPT vs INTERSECT
UnionDistinctQuery(
select_queries: slct_qrys,
limit_offset: _lmt_offst,
epilog: _epl,
) -> slct_qrys
UnionAllQuery(
select_queries: slct_qrys,
limit_offset: _lmt_offst,
epilog: _epl,
) -> slct_qrys
}
uq.select_queries
}

// pub fn union_query_set_limit(
// query qry: UnionQuery,
// limit lmt: Int,
// ) -> UnionQuery {
// let limit_offset = limit_new(lmt)
// UnionQuery(..qry, limit_offset: limit_offset)
// }
pub fn union_query_set_limit(
query qry: UnionQuery,
limit lmt: Int,
) -> UnionQuery {
let limit_offset = limit_new(lmt)
UnionQuery(..qry, limit_offset: limit_offset)
}

// pub fn union_query_set_limit_and_offset(
// query qry: UnionQuery,
// limit lmt: Int,
// offset offst: Int,
// ) -> UnionQuery {
// let limit_offset = limit_offset_new(limit: lmt, offset: offst)
// UnionQuery(..qry, limit_offset: limit_offset)
// }
pub fn union_query_set_limit_and_offset(
query qry: UnionQuery,
limit lmt: Int,
offset offst: Int,
) -> UnionQuery {
let limit_offset = limit_offset_new(limit: lmt, offset: offst)
UnionQuery(..qry, limit_offset: limit_offset)
}

// —————————————————————————————————————————————————————————————————————————— //
// ———— SelectQuery ————————————————————————————————————————————————————————— //
Expand All @@ -128,6 +130,7 @@ pub type SelectQuery {
// use order_by, limit and offset, possibly make them real types, too
// at least alias them
order_by: List(#(String, OrderByDirectionPart)),
epilog: EpilogPart,
)
}

Expand All @@ -143,6 +146,7 @@ pub fn select_query_new(
where: NoWherePart,
order_by: [],
limit_offset: NoLimitOffset,
epilog: NoEpilogPart,
)
}

Expand All @@ -153,6 +157,7 @@ pub fn select_query_new_from(from from: FromPart) -> SelectQuery {
where: NoWherePart,
order_by: [],
limit_offset: NoLimitOffset,
epilog: NoEpilogPart,
)
}

Expand All @@ -163,6 +168,7 @@ pub fn select_query_new_select(select select: List(SelectPart)) -> SelectQuery {
where: NoWherePart,
order_by: [],
limit_offset: NoLimitOffset,
epilog: NoEpilogPart,
)
}

Expand Down Expand Up @@ -618,3 +624,29 @@ pub fn limit_offset_apply(
pub fn limit_offset_get(select_query slct_qry: SelectQuery) -> LimitOffsetPart {
slct_qry.limit_offset
}

// —————————————————————————————————————————————————————————————————————————— //
// ———— Epilog Part ————————————————————————————————————————————————————————— //
// —————————————————————————————————————————————————————————————————————————— //

pub opaque type EpilogPart {
Epilog(string: String)
NoEpilogPart
}

pub fn epilog_new(epilog: String) -> EpilogPart {
case epilog {
"" -> NoEpilogPart
_ -> Epilog(string: epilog)
}
}

pub fn epilog_apply(
prepared_statement prp_stm: PreparedStatement,
epilog_part epl_prt: EpilogPart,
) -> PreparedStatement {
case epl_prt {
NoEpilogPart -> prp_stm
Epilog(string: epl) -> epl |> prepared_statement.with_sql(prp_stm, _)
}
}
5 changes: 2 additions & 3 deletions src/cake/prepared_statement_builder/select_builder.gleam
Original file line number Diff line number Diff line change
Expand Up @@ -71,9 +71,8 @@ fn maybe_add_limit_offset(
prepared_statement prp_stm: PreparedStatement,
select_query slct_qry: SelectQuery,
) -> PreparedStatement {
let lmt_offst =
query.limit_offset_get(slct_qry)
|> iox.dbg_label("lmt_offst")
let lmt_offst = query.limit_offset_get(slct_qry)
// |> iox.dbg_label("lmt_offst")

prp_stm
|> query.limit_offset_apply(lmt_offst)
Expand Down
25 changes: 10 additions & 15 deletions src/cake/prepared_statement_builder/union_builder.gleam
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import cake/internal/query.{
type SelectQuery, type UnionQuery, UnionAllQuery, UnionDistinctQuery,
type SelectQuery, type UnionQuery, UnionAll, UnionDistinct, UnionExcept,
UnionIntersect,
}
import cake/prepared_statement.{type PreparedStatement}
import cake/prepared_statement_builder/select_builder
Expand All @@ -22,20 +23,14 @@ pub fn apply_sql(
prepared_statement prp_stm: PreparedStatement,
select uq: UnionQuery,
) -> PreparedStatement {
let #(union_keyword, slct_qrys, lmt_offst, epl) = case uq {
UnionDistinctQuery(
select_queries: slct_qrys,
limit_offset: lmt_offst,
epilog: epl,
) -> #("UNION", slct_qrys, lmt_offst, epl)
UnionAllQuery(
select_queries: slct_qrys,
limit_offset: lmt_offst,
epilog: epl,
) -> #("UNION ALL", slct_qrys, lmt_offst, epl)
let union_keyword = case uq.union_kind {
UnionAll -> "UNION ALL"
UnionDistinct -> "UNION"
UnionExcept -> "EXCEPT"
UnionIntersect -> "INTERSECT"
}

slct_qrys
uq.select_queries
|> list.fold(
prp_stm,
fn(acc: PreparedStatement, sq: SelectQuery) -> PreparedStatement {
Expand All @@ -49,6 +44,6 @@ pub fn apply_sql(
}
},
)
|> query.limit_offset_apply(lmt_offst)
|> prepared_statement.with_sql(" " <> epl)
|> query.limit_offset_apply(uq.limit_offset)
|> query.epilog_apply(uq.epilog)
}

0 comments on commit 22c612d

Please sign in to comment.