34
35:- module(swish_csv, []). 36:- use_module(library(pengines), []). 37:- use_module(library(pairs)). 38:- use_module(library(csv), [csv_write_stream/3]). 39:- use_module(library(apply)). 40:- use_module(library(pprint)). 41:- use_module(library(option)).
53:- multifile
54 pengines:write_result/3,
55 write_answers/2, 56 write_answers/3.
63pengines:write_result(csv, Event, OptionDict) :-
64 ( Disposition = OptionDict.get(disposition)
65 -> Options = [disposition(Disposition)]
66 ; Options = []
67 ),
68 csv(Event, Options).
69
70csv(create(_Id, Features), Options) :- !,
71 memberchk(answer(Answer), Features),
72 csv(Answer, Options).
73csv(destroy(_Id, Wrapped), Options) :- !,
74 csv(Wrapped, Options).
75csv(success(_Id, Answers, Projection, _Time, More), Options) :- !,
76 VarTerm =.. [row|Projection],
77 success(Answers, VarTerm, [more(More)|Options]).
78csv(error(_Id, Error), _Options) :- !,
79 message_to_string(Error, Msg),
80 format('Status: 400 Bad request~n'),
81 format('Content-type: text/plain~n~n'),
82 format('ERROR: ~w~n', [Msg]).
83csv(output(_Id, message(_Term, _Class, HTML, _Where)), _Opts) :- !,
84 format('Status: 400 Bad request~n'),
85 format('Content-type: text/html~n~n'),
86 format('<html>~n~s~n</html>~n', [HTML]).
87csv(page(Page, Event), Options) :-
88 csv(Event, [page(Page)|Options]).
89csv(failure(_Id, _Time), Options) :- !,
90 success([], -, [more(false)|Options]).
91csv(Event, _) :-
92 print_term(Event, [output(user_error)]).
93
94success(Answers, VarTerm, Options) :-
95 write_answers(Answers, VarTerm, Options), !.
96success(Answers, VarTerm, Options) :-
97 write_answers(Answers, VarTerm), !,
98 assertion(\+option(page(_), Options)).
99success(Answers, _VarTerm, Options) :-
100 option(page(Page), Options),
101 Page > 1, !,
102 maplist(csv_answer, Answers, Rows),
103 forall(paginate(100, OutPage, Rows),
104 csv_write_stream(current_output, OutPage, [])).
105success(Answers, VarTerm, Options) :-
106 option(disposition(Disposition), Options, 'swish-result.csv'),
107 maplist(csv_answer, Answers, Rows),
108 format('Content-encoding: chunked~n'),
109 format('Content-disposition: attachment; filename="~w"~n', [Disposition]),
110 format('Content-type: text/csv~n~n'),
111 projection_row(VarTerm),
112 forall(paginate(100, Page, Rows),
113 csv_write_stream(current_output, Page, [])).
114
115projection_row(-) :- !.
116projection_row(row) :- !.
117projection_row(VarTerm) :-
118 csv_write_stream(current_output, [VarTerm], []).
119
120paginate(Len, Page, List) :-
121 length(Page0, Len),
122 ( append(Page0, Rest, List)
123 -> ( Page = Page0
124 ; paginate(Len, Page, Rest)
125 )
126 ; Page = List
127 ).
128
129
130csv_answer(JSON, Row) :-
131 is_dict(JSON), !,
132 dict_pairs(JSON, _, Pairs),
133 pairs_values(Pairs, Values),
134 maplist(csv_value, Values, CVSValues),
135 Row =.. [row|CVSValues].
136csv_answer(RowIn, Row) :-
137 compound(RowIn), !,
138 RowIn =.. [_|Values],
139 maplist(csv_value, Values, CVSValues),
140 Row =.. [row|CVSValues].
141
142csv_value(Var, '') :-
143 var(Var), !.
144csv_value(Number, Number) :-
145 number(Number), !.
146csv_value(Atom, Atom) :-
147 atom(Atom), !.
148csv_value(String, String) :-
149 string(String), !.
150csv_value(Term, Value) :-
151 term_string(Term, Value)
Support CSV output from a Pengines server
This module defines the result-format
csv
for Pengines. It allows SWISH users to post a query against the core Prolog system or a saved SWISH program and obtain the results using a simple web client such ascurl
. An example shell script is provided inclient/swish-ask.sh
.