Skip to content

Commit 9edf159

Browse files
committed
Add Show/Hide combinators
1 parent 8149fcf commit 9edf159

File tree

7 files changed

+104
-16
lines changed

7 files changed

+104
-16
lines changed

src/FunSQL.jl

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -54,6 +54,7 @@ export
5454
funsql_from,
5555
funsql_fun,
5656
funsql_group,
57+
funsql_hide,
5758
funsql_highlight,
5859
funsql_in,
5960
funsql_into,
@@ -83,6 +84,7 @@ export
8384
funsql_rank,
8485
funsql_row_number,
8586
funsql_select,
87+
funsql_show,
8688
funsql_sort,
8789
funsql_sum,
8890
funsql_with

src/link.jl

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -27,13 +27,15 @@ end
2727

2828
function _select(t::RowType)
2929
refs = SQLQuery[]
30+
t.visible || return refs
3031
for (f, ft) in t.fields
3132
if ft isa ScalarType
33+
ft.visible || continue
3234
push!(refs, Get(f))
3335
else
3436
nested_refs = _select(ft)
3537
for nested_ref in nested_refs
36-
push!(refs, Nested(over = nested_ref, name = f))
38+
push!(refs, Nested(name = f, tail = nested_ref))
3739
end
3840
end
3941
end

src/nodes.jl

Lines changed: 9 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -54,17 +54,19 @@ terminal(q::SQLQuery) =
5454
Chain(q′, q) =
5555
convert(SQLQuery, q)(q′)
5656

57-
label(q::SQLQuery) =
58-
@something label(q.head) label(q.tail)
57+
function label(q::SQLQuery; default = :_)
58+
l = label(q.head)
59+
l !== nothing ? l : label(q.tail; default)
60+
end
5961

6062
label(n::AbstractSQLNode) =
6163
nothing
6264

63-
label(::Nothing) =
64-
:_
65+
label(::Nothing; default = :_) =
66+
default
6567

66-
label(q) =
67-
label(convert(SQLQuery, q))
68+
label(q; default = :_) =
69+
label(convert(SQLQuery, q); default)
6870

6971

7072
# A variant of SQLQuery for assembling a chain of identifiers.
@@ -922,6 +924,7 @@ include("nodes/order.jl")
922924
include("nodes/over.jl")
923925
include("nodes/partition.jl")
924926
include("nodes/select.jl")
927+
include("nodes/show.jl")
925928
include("nodes/sort.jl")
926929
include("nodes/variable.jl")
927930
include("nodes/where.jl")

src/nodes/internal.jl

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -302,7 +302,7 @@ PrettyPrinting.quoteof(n::FunSQLMacroNode, ctx::QuoteContext) =
302302
Expr(:macrocall, Symbol("@funsql"), n.line, !ctx.limit ? n.ex : :)
303303

304304
label(n::FunSQLMacroNode) =
305-
label(n.query)
305+
label(n.query, default = nothing)
306306

307307

308308
# Unwrap @funsql macro when displaying the query.

src/nodes/show.jl

Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
# Show/Hide nodes
2+
3+
mutable struct ShowNode <: TabularNode
4+
names::Vector{Symbol}
5+
visible::Bool
6+
label_map::FunSQL.OrderedDict{Symbol, Int}
7+
8+
function ShowNode(; names = [], visible = true, label_map = nothing)
9+
if label_map !== nothing
10+
new(names, visible, label_map)
11+
else
12+
n = new(names, visible, FunSQL.OrderedDict{Symbol, Int}())
13+
for (i, name) in enumerate(n.names)
14+
if name in keys(n.label_map)
15+
err = FunSQL.DuplicateLabelError(name, path = SQLQuery[n])
16+
throw(err)
17+
end
18+
n.label_map[name] = i
19+
end
20+
n
21+
end
22+
end
23+
end
24+
25+
ShowNode(names...; visible = true) =
26+
ShowNode(names = Symbol[names...], visible = visible)
27+
28+
const Show = SQLQueryCtor{ShowNode}(:Show)
29+
30+
Hide(args...; kws...) =
31+
Show(args...; kws..., visible = false)
32+
33+
const funsql_show = Show
34+
const funsql_hide = Hide
35+
36+
function FunSQL.PrettyPrinting.quoteof(n::ShowNode, ctx::QuoteContext)
37+
Expr(:call, n.visible ? :Show : :Hide, quoteof(n.names, ctx)...)
38+
end

src/resolve.jl

Lines changed: 28 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -423,7 +423,7 @@ end
423423

424424
function resolve(n::JoinNode, ctx)
425425
if n.swap
426-
ctx′ = ResolveContext(Ctx, tail = n.joinee)
426+
ctx′ = ResolveContext(ctx, tail = n.joinee)
427427
return resolve(JoinNode(joinee = ctx.tail, on = n.on, left = n.right, right = n.left, optional = n.optional), ctx′)
428428
end
429429
tail′ = resolve(ctx)
@@ -506,6 +506,33 @@ function resolve(n::SelectNode, ctx)
506506
Resolved(RowType(fields), tail = q′)
507507
end
508508

509+
function resolve(n::ShowNode, ctx)
510+
tail′ = resolve(ctx)
511+
t = row_type(tail′)
512+
for name in n.names
513+
ft = get(t.fields, name, EmptyType())
514+
if ft isa EmptyType
515+
throw(
516+
ReferenceError(
517+
REFERENCE_ERROR_TYPE.UNDEFINED_NAME,
518+
name = name,
519+
path = get_path(ctx)))
520+
end
521+
end
522+
fields = FieldTypeMap()
523+
for (f, ft) in t.fields
524+
if f in keys(n.label_map)
525+
if ft isa ScalarType
526+
ft = ScalarType(visible = n.visible)
527+
else
528+
ft = RowType(ft.fields, ft.group, visible = n.visible)
529+
end
530+
end
531+
fields[f] = ft
532+
end
533+
Resolved(RowType(fields, t.group, visible = t.visible), tail = tail′)
534+
end
535+
509536
function resolve_scalar(n::SortNode, ctx)
510537
tail′ = resolve_scalar(ctx)
511538
q′ = Sort(value = n.value, nulls = n.nulls, tail = tail′)

src/types.jl

Lines changed: 23 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -13,17 +13,27 @@ PrettyPrinting.quoteof(::EmptyType) =
1313
Expr(:call, nameof(EmptyType))
1414

1515
struct ScalarType <: AbstractSQLType
16+
visible::Bool
17+
18+
ScalarType(; visible = true) =
19+
new(visible)
1620
end
1721

18-
PrettyPrinting.quoteof(::ScalarType) =
19-
Expr(:call, nameof(ScalarType))
22+
function PrettyPrinting.quoteof(t::ScalarType)
23+
ex = Expr(:call, nameof(ScalarType))
24+
if !t.visible
25+
push!(ex.args, Expr(:kw, :visible, t.visible))
26+
end
27+
ex
28+
end
2029

2130
struct RowType <: AbstractSQLType
2231
fields::OrderedDict{Symbol, Union{ScalarType, RowType}}
2332
group::Union{EmptyType, RowType}
33+
visible::Bool
2434

25-
RowType(fields, group = EmptyType()) =
26-
new(fields, group)
35+
RowType(fields, group = EmptyType(); visible = true) =
36+
new(fields, group, visible)
2737
end
2838

2939
const FieldTypeMap = OrderedDict{Symbol, Union{ScalarType, RowType}}
@@ -43,6 +53,9 @@ function PrettyPrinting.quoteof(t::RowType)
4353
if !(t.group isa EmptyType)
4454
push!(ex.args, Expr(:kw, :group, quoteof(t.group)))
4555
end
56+
if !t.visible
57+
push!(ex.args, Expr(:kw, :visible, t.visible))
58+
end
4659
ex
4760
end
4861

@@ -54,8 +67,8 @@ const EMPTY_ROW = RowType()
5467
Base.intersect(::AbstractSQLType, ::AbstractSQLType) =
5568
EmptyType()
5669

57-
Base.intersect(::ScalarType, ::ScalarType) =
58-
ScalarType()
70+
Base.intersect(t1::ScalarType, t2::ScalarType) =
71+
ScalarType(visible = t1.visible || t2.visible)
5972

6073
function Base.intersect(t1::RowType, t2::RowType)
6174
if t1 === t2
@@ -71,7 +84,7 @@ function Base.intersect(t1::RowType, t2::RowType)
7184
end
7285
end
7386
group = intersect(t1.group, t2.group)
74-
RowType(fields, group)
87+
RowType(fields, group, visible = t1.visible || t2.visible)
7588
end
7689

7790

@@ -98,5 +111,8 @@ function Base.issubset(t1::RowType, t2::RowType)
98111
if !issubset(t1.group, t2.group)
99112
return false
100113
end
114+
if !t1.visible && t2.visible
115+
return false
116+
end
101117
return true
102118
end

0 commit comments

Comments
 (0)