_site/cover/msc_mm_query.COVER.html

1 %% Copyright (c) 2023 Peter Morgan <peter.james.morgan@gmail.com>
2 %%
3 %% Licensed under the Apache License, Version 2.0 (the "License");
4 %% you may not use this file except in compliance with the License.
5 %% You may obtain a copy of the License at
6 %%
7 %% http://www.apache.org/licenses/LICENSE-2.0
8 %%
9 %% Unless required by applicable law or agreed to in writing, software
10 %% distributed under the License is distributed on an "AS IS" BASIS,
11 %% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 %% See the License for the specific language governing permissions and
13 %% limitations under the License.
14
15 %% @doc Middleman dealing with the query process.
16
17 -module(msc_mm_query).
18
19
20 -export([callback_mode/0]).
21 -export([handle_event/4]).
22 -import(msc_statem, [nei/1]).
23 -include_lib("kernel/include/logger.hrl").
24
25
26 callback_mode() ->
27 3 handle_event_function.
28
29
30 handle_event({call, From},
31 {request, #{action := query} = Packet},
32 {query, From},
33 #{client_flags := ClientFlags} = Data) ->
34 3 {keep_state,
35 Data#{decoder := msmp_codec:decode(
36 scran_branch:alt(
37 [msmp_column_count:decode(),
38 msmp_packet_ok:decode(ClientFlags),
39 msmp_packet_error:decode(ClientFlags)])),
40 query => #{columns => #{definitions => []},
41 rows => []},
42 encoder := msmp_codec:encode(msmp_com_query:encode(ClientFlags))},
43 nei({send, #{packet => Packet, sequence => 0}})};
44
45 handle_event({call, _}, {request, _}, _, _) ->
46
:-(
{keep_state_and_data, postpone};
47
48 handle_event(
49 internal,
50 {recv,
51 #{packet := #{action := column_count, column_count := ColumnCount}}},
52 _,
53 #{query := #{columns := Columns} = Query} = Data) ->
54 1 {keep_state,
55 Data#{decoder := msmp_codec:decode(
56 msmp_column_definition:decode()),
57 query := Query#{columns := Columns#{count => ColumnCount}}}};
58
59 handle_event(internal,
60 {recv, #{packet := #{action := error} = Packet}},
61 {query, From},
62 Data) ->
63
:-(
{next_state,
64 authenticated,
65 maps:without([query], Data),
66 [pop_callback_module,
67 {reply,
68 From,
69 {error, maps:without([action], Packet)}}]};
70
71 handle_event(internal,
72 {recv, #{packet := #{action := ok} = Packet}},
73 {query, From},
74 Data) ->
75 2 {next_state,
76 authenticated,
77 maps:without([query], Data),
78 [pop_callback_module,
79 {reply,
80 From,
81 {ok, maps:without([action], Packet)}}]};
82
83 handle_event(
84 internal,
85 {recv, #{packet := #{action := column_definition} = Packet}},
86 _,
87 #{query := #{columns := #{definitions := Definitions,
88 count := ColumnCount}}})
89 when length(Definitions) + 1 < ColumnCount ->
90
:-(
{keep_state_and_data, nei({add_definition, Packet})};
91
92 handle_event(
93 internal,
94 {recv, #{packet := #{action := column_definition} = Packet}},
95 _,
96 #{client_flags := ClientFlags} = Data) ->
97 1 {keep_state,
98 Data#{decoder := msmp_codec:decode(
99 scran_branch:alt(
100 [msmp_text_resultset_row:decode(),
101 msmp_packet_eof:decode(ClientFlags)]))},
102 nei({add_definition, Packet})};
103
104 handle_event(
105 internal,
106 {add_definition, Packet},
107 _,
108 #{query := #{columns := #{definitions := Defs} = Cols} = Query} = Data) ->
109 1 {keep_state,
110 Data#{query := Query#{columns := Cols#{definitions := Defs ++
111 [maps:without(
112 [action],
113 Packet)]}}}};
114
115 handle_event(
116 internal,
117 {recv, #{packet := #{action := text_resultset_row, row := Row}}},
118 _,
119 #{query := #{columns := #{definitions := Definitions}}}) ->
120 1 {keep_state_and_data,
121 nei({add_row,
122 lists:map(
123 fun
124 ({Definition, Column}) ->
125 1 {<<>>, Decoded} = (msmp_text:decode(Definition))(Column),
126 1 Decoded
127 end,
128 lists:zip(Definitions, Row))})};
129
130 handle_event(internal,
131 {add_row, Row},
132 _,
133 #{query := #{rows := Rows} = Query} = Data) ->
134 1 {keep_state,
135 Data#{query := Query#{rows := [Row | Rows]}}};
136
137 handle_event(internal,
138 {recv, #{packet := #{action := eof}}},
139 {query, From},
140 #{query := #{columns := #{definitions := Columns},
141 rows := Rows}} = Data) ->
142 1 {next_state,
143 authenticated,
144 maps:without([query], Data),
145 [pop_callback_module,
146 {reply,
147 From,
148 {lists:map(
149 fun
150 (Column) ->
151 1 maps:with([catalog, schema, name, table, type], Column)
152 end,
153 Columns),
154 lists:reverse(Rows)}}]};
155
156 handle_event(EventType, EventContent, State, Data) ->
157 56 msc_mm_common:handle_event(EventType,
158 EventContent,
159 State,
160 Data).
Line Hits Source