summaryrefslogtreecommitdiff
path: root/deps/goldrush/src/glc_ops.erl
blob: 8b093ce324f04c26a895bc2ed017655467c2c0d1 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
%% @doc Built in operators.
-module(glc_ops).

-export([
    lt/2, lte/2,
    eq/2,
    gt/2, gte/2,
    wc/1,
    nf/1
]).

-export([
    all/1,
    any/1,
    null/1,
    with/2
]).

-export([
    union/1
]).

-type op() ::
    {atom(), '=<', term()} |
    {atom(), '=', term()} |
    {atom(), '>', term()} |
    {atom(), '>=', term()} |
    {atom(), '*'} |
    {atom(), '!'} |
    {any, [op(), ...]} |
    {all, [op(), ...]} |
    {null, true|false}.

-export_type([op/0]).

%% @doc Test that a field value is less than a term.
-spec lt(atom(), term()) -> op().
lt(Key, Term) when is_atom(Key) ->
    {Key, '<', Term};
lt(Key, Term) ->
    erlang:error(badarg, [Key, Term]).


%% @doc Test that a field value is less than or equal to a term.
-spec lte(atom(), term()) -> op().
lte(Key, Term) when is_atom(Key) ->
    {Key, '=<', Term};
lte(Key, Term) ->
    erlang:error(badarg, [Key, Term]).

%% @doc Test that a field value is equal to a term.
-spec eq(atom(), term()) -> op().
eq(Key, Term) when is_atom(Key) ->
    {Key, '=', Term};
eq(Key, Term) ->
    erlang:error(badarg, [Key, Term]).

%% @doc Test that a field value is greater than a term.
-spec gt(atom(), term()) -> op().
gt(Key, Term) when is_atom(Key) ->
    {Key, '>', Term};
gt(Key, Term) ->
    erlang:error(badarg, [Key, Term]).

%% @doc Test that a field value is greater than or equal to a term.
-spec gte(atom(), term()) -> op().
gte(Key, Term) when is_atom(Key) ->
    {Key, '>=', Term};
gte(Key, Term) ->
    erlang:error(badarg, [Key, Term]).

%% @doc Test that a field exists.
-spec wc(atom()) -> op().
wc(Key) when is_atom(Key) ->
    {Key, '*'};
wc(Key) ->
    erlang:error(badarg, [Key]).

%% @doc Test that a field is not found.
-spec nf(atom()) -> op().
nf(Key) when is_atom(Key) ->
    {Key, '!'};
nf(Key) ->
    erlang:error(badarg, [Key]).

%% @doc Filter the input using multiple filters.
%%
%% For an input to be considered valid output the all filters specified
%% in the list must hold for the input event. The list is expected to
%% be a non-empty list. If the list of filters is an empty list a `badarg'
%% error will be thrown.
-spec all([op()]) -> op().
all([_|_]=Conds) ->
    {all, Conds};
all(Other) ->
    erlang:error(badarg, [Other]).

%% @doc Filter the input using one of multiple filters.
%%
%% For an input to be considered valid output on of the filters specified
%% in the list must hold for the input event. The list is expected to be
%% a non-empty list. If the list of filters is an empty list a `badarg'
%% error will be thrown.
-spec any([op()]) -> op().
any([_|_]=Conds) ->
    {any, Conds};
any(Other) ->
    erlang:error(badarg, [Other]).


%% @doc Always return `true' or `false'.
-spec null(boolean()) -> op().
null(Result) when is_boolean(Result) ->
    {null, Result};
null(Result) ->
    erlang:error(badarg, [Result]).

%% @doc Apply a function to each output of a query.
%%
%% Updating the output action of a query finalizes it. Attempting
%% to use a finalized query to construct a new query will result
%% in a `badarg' error.
-spec with(op(), fun((gre:event()) -> term())) -> op().
with(Query, Fun) when is_function(Fun, 1);
                      is_function(Fun, 2) ->
    {with, Query, Fun};
with(Query, Fun) ->
    erlang:error(badarg, [Query, Fun]).

%% @doc Return a union of multiple queries.
%%
%% The union of multiple queries is the equivalent of executing multiple
%% queries separately on the same input event. The advantage is that filter
%% conditions that are common to all or some of the queries only need to
%% be tested once.
%%
%% All queries are expected to be valid and have an output action other
%% than the default which is `output'. If these expectations don't hold
%% a `badarg' error will be thrown.
-spec union([op()]) -> op().
union(Queries) ->
    case [Query || Query <- Queries, glc_lib:onoutput(Query) =:= output] of
        [] -> {union, Queries};
        [_|_] -> erlang:error(badarg, [Queries])
    end.