Skip to content

Commit 1396a36

Browse files
committed
Add Show/Hide combinators
1 parent 6a0d232 commit 1396a36

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
@@ -415,7 +415,7 @@ end
415415

416416
function resolve(n::JoinNode, ctx)
417417
if n.swap
418-
ctx′ = ResolveContext(Ctx, tail = n.joinee)
418+
ctx′ = ResolveContext(ctx, tail = n.joinee)
419419
return resolve(JoinNode(joinee = ctx.tail, on = n.on, left = n.right, right = n.left, optional = n.optional), ctx′)
420420
end
421421
tail′ = resolve(ctx)
@@ -498,6 +498,33 @@ function resolve(n::SelectNode, ctx)
498498
Resolved(RowType(fields), tail = q′)
499499
end
500500

501+
function resolve(n::ShowNode, ctx)
502+
tail′ = resolve(ctx)
503+
t = row_type(tail′)
504+
for name in n.names
505+
ft = get(t.fields, name, EmptyType())
506+
if ft isa EmptyType
507+
throw(
508+
ReferenceError(
509+
REFERENCE_ERROR_TYPE.UNDEFINED_NAME,
510+
name = name,
511+
path = get_path(ctx)))
512+
end
513+
end
514+
fields = FieldTypeMap()
515+
for (f, ft) in t.fields
516+
if f in keys(n.label_map)
517+
if ft isa ScalarType
518+
ft = ScalarType(visible = n.visible)
519+
else
520+
ft = RowType(ft.fields, ft.group, visible = n.visible)
521+
end
522+
end
523+
fields[f] = ft
524+
end
525+
Resolved(RowType(fields, t.group, visible = t.visible), tail = tail′)
526+
end
527+
501528
function resolve_scalar(n::SortNode, ctx)
502529
tail′ = resolve_scalar(ctx)
503530
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)