34
35:- module(table_util,
36 [ sort_table/2, 37 verify_table_order/1 38 ]). 39:- use_module(library(table)). 40
56
57
62
63sort_table(Table, File) :-
64 open(File, write, OutFd), 65 get_table_attribute(Table, key_field, Key),
66 !,
67 get_table_attribute(Table, field(Key), Term),
68 get_table_attribute(Table, file, InFile),
69 functor(Term, KeyName, _),
70 arg(2, Term, Attributes),
71 format('Sorting table "~w" ', [InFile]),
72 ( memberchk(sorted(Order), Attributes)
73 -> true
74 ; memberchk(sorted, Attributes),
75 Order = exact
76 ),
77 format('sorted(~w) on field "~w" ... ', [Order, KeyName]),
78 flush,
79 read_table(Table, KeyName, Fields),
80 sort_fields(Order, Fields, SortedFields),
81 write_table(SortedFields, Table, OutFd),
82 close(OutFd),
83 format('done.~n', []).
84
85read_table(Table, KeyName, Fields) :-
86 format('(reading) ... ', []), flush,
87 read_table(Table, KeyName, 0, Fields).
88
89read_table(Table, KeyName, From, [KeyValue-From|T]) :-
90 read_field(Table, From, To, KeyName, KeyValue),
91 !,
92 read_table(Table, KeyName, To, T).
93read_table(_, _, _, []).
94
95sort_fields(Order, Fields, Sorted) :-
96 length(Fields, N),
97 format('(sorting ~D records) ... ', [N]), flush,
98 sort_keyed_strings(Order, Fields, Sorted).
99
100write_table(Records, Table, OutFd) :-
101 format('(writing) ... ', []), flush,
102 get_table_attribute(Table, record_separator, Sep),
103 write_records(Records, Table, Sep, OutFd).
104
105write_records([], _, _, _).
106write_records([_-From|T], Table, Sep, OutFd) :-
107 read_table_record_data(Table, From, _To, RecordData),
108 format(OutFd, '~s~c', [RecordData, Sep]),
109 write_records(T, Table, Sep, OutFd).
110
111
116
117sort_keyed_strings(Table, List, Sorted) :-
118 length(List, Length),
119 do_sort(Length, Table, List, _, Result),
120 Sorted = Result.
121
122do_sort(2, Table, [X1, X2|L], L, R) :-
123 !,
124 X1 = K1-_,
125 X2 = K2-_,
126 compare_strings(Table, K1, K2, Cmp),
127 merge2(Cmp, X1, X2, R).
128do_sort(1, _, [X|L], L, [X]) :- !.
129do_sort(0, _, L, L, []) :- !.
130do_sort(N, Table, L1, L3, R) :-
131 N1 is N // 2,
132 N2 is N - N1,
133 do_sort(N1, Table, L1, L2, R1),
134 do_sort(N2, Table, L2, L3, R2),
135 do_merge(R1, R2, Table, R).
136
137do_merge([], R, _, R) :- !.
138do_merge(R, [], _, R) :- !.
139do_merge(R1, R2, Table, [X|R]) :-
140 R1 = [X1|R1a],
141 R2 = [X2|R2a],
142 X1 = K1-_,
143 X2 = K2-_,
144 ( compare_strings(Table, K1, K2, >)
145 -> X = X2, do_merge(R1, R2a, Table, R)
146 ; X = X1, do_merge(R1a, R2, Table, R)
147 ).
148
149merge2(>, A, B, [B, A]) :- !.
150merge2(_, A, B, [A, B]).
151
152
153 156
160
161verify_table_order(Table) :-
162 get_table_attribute(Table, key_field, Key),
163 !,
164 get_table_attribute(Table, field(Key), Term),
165 get_table_attribute(Table, file, File),
166 functor(Term, KeyName, _),
167 arg(2, Term, Attributes),
168 format('Checking "~w" ', [File]),
169 ( memberchk(sorted(Order), Attributes)
170 -> true
171 ; memberchk(sorted, Attributes),
172 Order = exact
173 ),
174 ( memberchk(unique, Attributes)
175 -> Cmp = >,
176 format('uniquely ', [])
177 ; Cmp = [>, =]
178 ),
179 format('sorted(~w) on field "~w" ... ', [Order, KeyName]),
180 flush,
181 read_field(Table, 0, To, KeyName, KeyValue),
182 verify_table(Table, To, KeyName, KeyValue, Order, Cmp),
183 format('done.~n', []).
184
185verify_table(Table, From, KeyName, PrevValue, Order, Cmp) :-
186 read_field(Table, From, To, KeyName, KeyValue),
187 !,
188 ( compare_strings(Order, KeyValue, PrevValue, Rval),
189 ok_cmp(Rval, Cmp)
190 -> verify_table(Table, To, KeyName, KeyValue, Order, Cmp)
191 ; format('~N!! Order conflict: ~w < ~w~n', [KeyValue, PrevValue]),
192 verify_table(Table, To, KeyName, KeyValue, Order, Cmp)
193 ).
194verify_table(_, _, _, _, _, _).
195
196ok_cmp(Cmp, Cmp) :- !.
197ok_cmp(Cmp, List) :-
198 memberchk(Cmp, List).
199
200read_field(Table, From, To, Field, Value) :-
201 functor(Term, Field, 1),
202 read_table_fields(Table, From, To, [Term]),
203 arg(1, Term, Value)