Skip to content

Commit 11e9d3d

Browse files
committed
options propagation, implement inner join
1 parent 9a66554 commit 11e9d3d

8 files changed

Lines changed: 157 additions & 98 deletions

File tree

src/QueryOperators.jl

Lines changed: 53 additions & 38 deletions
Original file line numberDiff line numberDiff line change
@@ -1,82 +1,97 @@
1+
function as(new_name_model_row::Pair{Symbol, <: SourceCode}; options...)
2+
SQLExpression(:AS,
3+
translate(new_name_model_row.second.code; options...),
4+
new_name_model_row.first
5+
)
6+
end
7+
18
@code_instead QueryOperators.drop SourceCode Integer
2-
@simple_translate ::typeof(QueryOperators.drop) :OFFSET
9+
@translate ::typeof(QueryOperators.drop) :OFFSET
310

411
@code_instead QueryOperators.filter SourceCode Any Expr
5-
function translate_dispatch(::typeof(QueryOperators.filter), iterator, call, call_expression)
12+
function translate_dispatch(::typeof(QueryOperators.filter), iterator, call, call_expression; options...)
613
SQLExpression(:WHERE,
7-
translate(iterator),
8-
translate(call(model_row(iterator)).code)
14+
translate(iterator; options...),
15+
translate(call(model_row(iterator)).code; options...)
916
)
1017
end
1118

1219
@code_instead QueryOperators.join SourceCode SourceCode Any Expr Any Expr Any Expr
13-
function translate_dispatch(::typeof(QueryOperators.join), source1, source2,
14-
key1, key1_expression,
15-
key2, key2_expression,
16-
combine, combine_expression
17-
)
18-
SQLExpression(:on,
19-
SQLExpression(:INNER_JOIN, translate(source1), translate(source2)),
20-
SQLExpression(:(=), translate(key1), translate(key2))
20+
function translate_dispatch(::typeof(QueryOperators.join), source1, source2, key1, key1_expression, key2, key2_expression, combine, combine_expression; options...)
21+
model_row_1 = model_row(source1; other = true)
22+
model_row_2 = model_row(source2; other = true)
23+
SQLExpression(:ON,
24+
SQLExpression(Symbol("INNER JOIN"),
25+
SQLExpression(:SELECT,
26+
translate(source1; options...),
27+
Generator(
28+
pair -> as(pair; options...),
29+
pairs(combine(model_row_1, model_row_2))
30+
)...
31+
),
32+
translate(source2; other = true, options...)
33+
),
34+
SQLExpression(:(=),
35+
translate(key1(model_row_1).code; options...),
36+
translate(key2(model_row_2).code; other = true, options...)
37+
)
2138
)
2239
end
2340

2441
@code_instead QueryOperators.orderby SourceCode Any Expr
25-
function translate_dispatch(::typeof(QueryOperators.orderby), unordered, key_function, key_function_expression)
42+
function translate_dispatch(::typeof(QueryOperators.orderby), unordered, key_function, key_function_expression; options...)
2643
SQLExpression(Symbol("ORDER BY"),
27-
translate(unordered),
28-
translate(key_function(model_row(unordered)).code)
44+
translate(unordered; options...),
45+
translate(key_function(model_row(unordered)).code; options...)
2946
)
3047
end
3148
@code_instead QueryOperators.thenby SourceCode Any Expr
32-
function translate_dispatch(::typeof(QueryOperators.thenby), unordered, key_function, key_function_expression)
33-
original = translate(unordered)
49+
function translate_dispatch(::typeof(QueryOperators.thenby), unordered, key_function, key_function_expression; options...)
50+
original = translate(unordered; options...)
3451
SQLExpression(original.call, original.arguments...,
35-
translate(key_function(model_row(unordered)).code)
52+
translate(key_function(model_row(unordered)).code; options...)
3653
)
3754
end
3855

3956
@code_instead QueryOperators.orderby_descending SourceCode Any Expr
40-
function translate_dispatch(::typeof(QueryOperators.orderby_descending), unordered, key_function, key_function_expression)
57+
function translate_dispatch(::typeof(QueryOperators.orderby_descending), unordered, key_function, key_function_expression; options...)
4158
SQLExpression(Symbol("ORDER BY"),
42-
translate(unordered),
59+
translate(unordered; options...),
4360
SQLExpression(:DESC,
44-
translate(key_function(model_row(unordered)).code)
61+
translate(key_function(model_row(unordered)).code; options...)
4562
)
4663
)
4764
end
4865
@code_instead QueryOperators.thenby_descending SourceCode Any Expr
49-
function translate_dispatch(::typeof(QueryOperators.thenby_descending), unordered, key_function, key_function_expression)
50-
original = translate(unordered)
66+
function translate_dispatch(::typeof(QueryOperators.thenby_descending), unordered, key_function, key_function_expression; options...)
67+
original = translate(unordered; options...)
5168
SQLExpression(original.call, original.arguments...,
5269
SQLExpression(:DESC,
53-
translate(key_function(model_row(unordered)).code)
70+
translate(key_function(model_row(unordered)).code; options...)
5471
)
5572
)
5673
end
5774

5875
@code_instead QueryOperators.map SourceCode Any Expr
59-
function model_row_dispatch(::typeof(QueryOperators.map), iterator, call, call_expression)
60-
call(model_row(iterator))
76+
function model_row_dispatch(::typeof(QueryOperators.map), iterator, call, call_expression; options...)
77+
call(model_row(iterator; options...))
6178
end
62-
function select_as(new_name_model_row::Pair{Symbol, <: SourceCode})
63-
SQLExpression(:AS,
64-
new_name_model_row.first,
65-
translate(new_name_model_row.second.code),
66-
)
67-
end
68-
function translate_dispatch(::typeof(QueryOperators.map), select_table, call, call_expression)
79+
80+
function translate_dispatch(::typeof(QueryOperators.map), select_table, call, call_expression; options...)
6981
SQLExpression(
70-
Symbol("SELECT"), translate(select_table),
71-
Generator(select_as, pairs(call(model_row(select_table))))...
82+
Symbol("SELECT"), translate(select_table; options...),
83+
Generator(
84+
pair -> as(pair; options...),
85+
pairs(call(model_row(select_table; options...)))
86+
)...
7287
)
7388
end
7489

7590
@code_instead QueryOperators.take SourceCode Any
76-
@simple_translate ::typeof(QueryOperators.take) :LIMIT
91+
@translate ::typeof(QueryOperators.take) :LIMIT
7792

7893
@code_instead QueryOperators.unique SourceCode Any Expr
79-
function translate_dispatch(::typeof(QueryOperators.unique), repeated, key_function, key_function_expression)
80-
result = translate(repeated)
94+
function translate_dispatch(::typeof(QueryOperators.unique), repeated, key_function, key_function_expression; options...)
95+
result = translate(repeated; options...)
8196
SQLExpression(Symbol(string(result.call, " DISTINCT")), result.arguments...)
8297
end

src/QuerySQLite.jl

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -21,10 +21,10 @@ import TableTraits: isiterabletable
2121

2222
include("utilities.jl")
2323
include("source.jl")
24-
include("translate.jl")
25-
include("realize.jl")
2624
include("iterate.jl")
25+
include("translate.jl")
2726
include("library.jl")
2827
include("QueryOperators.jl")
28+
include("realize.jl")
2929

3030
end # module

src/iterate.jl

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
struct SQLiteCursor{Row}
22
statement::Stmt
33
status::RefValue{Cint}
4-
cursor_model_row::RefValue{Int}
4+
cursor_row::RefValue{Int}
55
end
66

77
function eltype(::SQLiteCursor{Row}) where {Row}
@@ -49,21 +49,21 @@ function iterate(cursor::SQLiteCursor{Row}) where {Row}
4949
nothing
5050
else
5151
named_tuple = generate_namedtuple(Row, cursor)
52-
cursor.cursor_model_row[] = 1
52+
cursor.cursor_row[] = 1
5353
named_tuple, 1
5454
end
5555
end
5656

5757
function iterate(cursor::SQLiteCursor{Row}, state) where {Row}
58-
if state != cursor.cursor_model_row[]
58+
if state != cursor.cursor_row[]
5959
error("State does not match SQLiteCursor model_row")
6060
else
6161
cursor.status[] = sqlite3_step(cursor.statement.handle)
6262
if isdone(cursor)
6363
nothing
6464
else
6565
named_tuple = generate_namedtuple(Row, cursor)
66-
cursor.cursor_model_row[] = state + 1
66+
cursor.cursor_row[] = state + 1
6767
named_tuple, state + 1
6868
end
6969
end

src/library.jl

Lines changed: 50 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -1,46 +1,58 @@
11
@code_instead (==) SourceCode Any
22
@code_instead (==) Any SourceCode
33
@code_instead (==) SourceCode SourceCode
4-
@simple_translate ::typeof(==) :(=)
4+
@translate ::typeof(==) :(=)
55

66
@code_instead (!=) SourceCode Any
77
@code_instead (!=) Any SourceCode
88
@code_instead (!=) SourceCode SourceCode
9-
@simple_translate ::typeof(!=) Symbol("<>")
9+
@translate ::typeof(!=) Symbol("<>")
1010

1111
@code_instead (!) SourceCode
12-
@simple_translate ::typeof(!) :NOT
12+
@translate ::typeof(!) :NOT
1313

1414
@code_instead (&) SourceCode Any
1515
@code_instead (&) Any SourceCode
1616
@code_instead (&) SourceCode SourceCode
17-
@simple_translate ::typeof(&) :AND
17+
@translate ::typeof(&) :AND
1818

1919
@code_instead (|) SourceCode Any
2020
@code_instead (|) Any SourceCode
2121
@code_instead (|) SourceCode SourceCode
22-
@simple_translate ::typeof(|) :OR
22+
@translate ::typeof(|) :OR
2323

2424
@code_instead coalesce SourceCode Vararg{Any}
25-
@simple_translate ::typeof(coalesce) :COALESCE
25+
@translate ::typeof(coalesce) :COALESCE
2626

2727
function get_column(source_row, column_name)
2828
SourceCode(source_row.source, Expr(:call, getproperty, source_row, column_name))
2929
end
30-
function model_row_dispatch(::typeof(getproperty), source_tables::SourceTables, table_name)
30+
function model_row_dispatch(::typeof(getproperty), source_tables::SourceTables, table_name; other = false, options...)
3131
source = get_source(source_tables)
3232
column_names = get_column_names(source, table_name)
3333
NamedTuple{column_names}(partial_map(
3434
get_column,
35-
SourceRow(source, table_name),
35+
if other
36+
SourceOtherRow(source, table_name)
37+
else
38+
SourceRow(source, table_name)
39+
end,
3640
column_names
3741
))
3842
end
39-
function translate_dispatch(::typeof(getproperty), source_tables::SourceTables, table_name)
40-
SQLExpression(:FROM, translate(table_name))
43+
function translate_dispatch(::typeof(getproperty), source_tables::SourceTables, table_name; other = false, options...)
44+
if other
45+
translate(table_name)
46+
else
47+
SQLExpression(:FROM, translate(table_name))
48+
end
4149
end
42-
function translate_dispatch(::typeof(getproperty), source_row::SourceRow, column_name)
43-
SQLExpression(:., source_row.table_name, translate(column_name))
50+
function translate_dispatch(::typeof(getproperty), source_row::SourceRow, column_name; options...)
51+
translate(column_name; options...)
52+
end
53+
54+
function translate_dispatch(::typeof(getproperty), source_row::SourceOtherRow, column_name; options...)
55+
SQLExpression(:., source_row.table_name, translate(column_name; options...))
4456
end
4557

4658
"""
@@ -70,47 +82,62 @@ export if_else
7082
@code_instead if_else SourceCode Any SourceCode
7183
@code_instead if_else SourceCode SourceCode Any
7284
@code_instead if_else SourceCode SourceCode SourceCode
73-
@simple_translate ::typeof(if_else) :IF
85+
@translate ::typeof(if_else) :IF
7486

7587
@code_instead in SourceCode Any
7688
@code_instead in Any SourceCode
7789
@code_instead in SourceCode SourceCode
78-
@simple_translate ::typeof(in) :IN
90+
@translate ::typeof(in) :IN
7991

8092
@code_instead isequal SourceCode Any
8193
@code_instead isequal Any SourceCode
8294
@code_instead isequal SourceCode SourceCode
83-
@simple_translate ::typeof(isequal) Symbol("IS NOT DISTINCT FROM")
95+
@translate ::typeof(isequal) Symbol("IS NOT DISTINCT FROM")
8496

8597
@code_instead isless SourceCode Any
8698
@code_instead isless Any SourceCode
8799
@code_instead isless SourceCode SourceCode
88-
@simple_translate ::typeof(isless) :<
100+
@translate ::typeof(isless) :<
89101

90102
@code_instead ismissing SourceCode
91-
@simple_translate ::typeof(ismissing) Symbol("IS NULL")
103+
@translate ::typeof(ismissing) Symbol("IS NULL")
92104

93105
@code_instead occursin AbstractString SourceCode
94106
@code_instead occursin Regex SourceCode
95-
translate_dispatch(::typeof(occursin), needle::AbstractString, haystack) =
107+
translate_dispatch(::typeof(occursin), needle::AbstractString, haystack; options...) =
96108
SQLExpression(
97109
:LIKE,
98-
translate(haystack),
110+
translate(haystack; options...),
99111
string('%', needle, '%')
100112
)
101-
translate_dispatch(::typeof(occursin), needle::Regex, haystack) =
113+
translate_dispatch(::typeof(occursin), needle::Regex, haystack; options...) =
102114
SQLExpression(
103115
:LIKE,
104-
translate(haystack),
116+
translate(haystack; options...),
105117
replace(replace(needle.pattern, r"(?<!\\)\.\*" => "%"), r"(?<!\\)\." => "_")
106118
)
107-
@simple_translate ::typeof(occursin) :LIKE
119+
@translate ::typeof(occursin) :LIKE
108120

109121
@code_instead startswith SourceCode Any
110122
@code_instead startswith Any SourceCode
111123
@code_instead startswith SourceCode SourceCode
112124

113-
translate_dispatch(::typeof(startswith), full, prefix::AbstractString) =
125+
126+
@code_instead secondary SourceCode
127+
"""
128+
A dummy function for marking a secondary table
129+
"""
130+
function secondary(something)
131+
something
132+
end
133+
translate_dispatch(::typeof(startswith), full, prefix::AbstractString; options...) =
134+
SQLExpression(
135+
:LIKE,
136+
translate(full),
137+
string(prefix, '%')
138+
)
139+
140+
translate_dispatch(::typeof(startswith), full, prefix::AbstractString; options...) =
114141
SQLExpression(
115142
:LIKE,
116143
translate(full),

src/realize.jl

Lines changed: 15 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -27,18 +27,22 @@ function binary(sql_expression)
2727
end
2828
end
2929

30-
function just_second(sql_expression)
30+
function tight_binary(sql_expression)
3131
if length(sql_expression.arguments) != 2
3232
throw(ArgumentsNumberException(sql_expression.call, 2))
3333
else
34-
realize(sql_expression.arguments[2])
34+
string(
35+
realize(sql_expression.arguments[1]),
36+
sql_expression.call,
37+
realize(sql_expression.arguments[2]),
38+
)
3539
end
3640
end
3741

3842
function function_call(sql_expression)
3943
string(
40-
sql_expression.call,
41-
join(map_unrolled(realize, sql_expression.arguments), ", ")
44+
sql_expression.call, "(",
45+
join(map_unrolled(realize, sql_expression.arguments), ", "), ")"
4246
)
4347
end
4448

@@ -50,15 +54,15 @@ function postfix(sql_expression)
5054
end
5155
end
5256

53-
function select_pattern(sql_expression)
57+
function rest_first(sql_expression)
5458
realized_arguments = map_unrolled(realize, sql_expression.arguments)
5559
string(sql_expression.call, " ",
5660
join(realized_arguments[2:end], ", "),
5761
" ", realized_arguments[1]
5862
)
5963
end
6064

61-
function order_by_pattern(sql_expression)
65+
function first_result(sql_expression)
6266
realized_arguments = map_unrolled(realize, sql_expression.arguments)
6367
string(realized_arguments[1], " ",
6468
sql_expression.call, " ",
@@ -71,7 +75,7 @@ function realize(something)
7175
end
7276

7377
function realize(sql_expression::SQLExpression)
74-
if sql_expression.call == :COALESCE
78+
if in(sql_expression.call, (:COALESCE,))
7579
function_call(sql_expression)
7680
elseif sql_expression.call == :IF && length(sql_expression.arguments) == 3
7781
string("CASE WHEN", realize(sql_expressions.arguments[1]),
@@ -80,12 +84,12 @@ function realize(sql_expression::SQLExpression)
8084
)
8185
elseif in(sql_expression.call, (:DESC, Symbol("IS NULL")))
8286
postfix(sql_expression)
83-
elseif in(sql_expression.call, (:.,))
84-
just_second(sql_expression)
8587
elseif in(sql_expression.call, (:SELECT, Symbol("SELECT DISTINCT")))
86-
select_pattern(sql_expression)
88+
rest_first(sql_expression)
8789
elseif in(sql_expression.call, (Symbol("ORDER BY"),))
88-
order_by_pattern(sql_expression)
90+
first_result(sql_expression)
91+
elseif in(sql_expression.call, (:.,))
92+
tight_binary(sql_expression)
8993
elseif length(sql_expression.arguments) == 1
9094
unary(sql_expression)
9195
elseif length(sql_expression.arguments) == 2

0 commit comments

Comments
 (0)