Files
secondo/Optimizer/NestedRelations/auxiliary.pl

1024 lines
24 KiB
Perl
Raw Normal View History

2026-01-23 17:03:45 +08:00
/*
----
This file is part of SECONDO.
Copyright (C) 2004-2008, University in Hagen, Faculty of Mathematics and
Computer Science, Database Systems for New Applications.
SECONDO is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
SECONDO is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with SECONDO; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
----
1 Auxiliary Predicates
This file contains the pretty-printing predicate
~pretty\_print~ and various auxiliary predicates for
~pretty\_print~ and a ~secondo~ predicate which uses just
one argument (the command) and pretty-prints the result.
1.1 Predicate ~pretty\_print~
Predicate ~pretty\_print~ prints a list L which is assumed to
be a PROLOG representation of a
Secondo nested list. That is the case e.g.
if L is output by the ~secondo~ predicate. If L is a relation,
a special output format is used which makes reading the
output more comfortable. That output format closely resembles
the output format used by SecondoTTY.
1.1.1 Predicates Auxiliary to Predicate ~pretty\_print~
*/
is_atomic_list([]).
is_atomic_list([Head | Tail]) :-
atomic(Head),
is_atomic_list(Tail).
write_spaces(0).
write_spaces(N) :-
N > 0,
write(' '),
N1 is N - 1,
write_spaces(N1).
write_tabs(N) :-
N1 is 2 * N ,
write_spaces(N1).
write_atoms([X]) :-
!,
write(X).
write_atoms([X | Rest]) :-
write(X),
write(', '),
write_atoms(Rest).
write_element(X, N) :-
atomic(X),
write_tabs(N),
write(X).
write_element(X, N) :-
is_atomic_list(X),
!,
write_tabs(N),
write('['),
write_atoms(X),
write(']').
write_element(X, N) :-
is_list(X),
N1 is N + 1,
write_tabs(N),
write('['),
nl,
write_elements(X, N1),
write(']').
write_elements([], _).
write_elements([X], N) :-
!,
write_element(X, N).
write_elements([X | L], N) :-
write_element(X, N),
write(','),
nl,
write_elements(L, N).
max_attr_length([], 0).
max_attr_length([[Name, _] | AttrDescription], M) :-
max_attr_length(AttrDescription, M1),
atom_length(Name, M2),
M is max(M1, M2).
write_tuple([], [], _).
write_tuple([[Name, _] | RestOfAttr], [AttrValue | RestOfValues], M) :-
write(Name),
atom_length(Name, NLength),
PadLength is M - NLength,
write_spaces(PadLength),
write(' : '),
write(AttrValue),
nl,
write_tuple(RestOfAttr, RestOfValues, M).
write_tuples(_, [], _).
write_tuples(AttrDescription, [Tuple], M) :-
!,
write_tuple(AttrDescription, Tuple, M).
write_tuples(AttrDescription, [Tuple | TupleList], M) :-
write_tuple(AttrDescription, Tuple, M),
nl,
write_tuples(AttrDescription, TupleList, M).
/*
1.1.2 Predicate ~pretty\_print~
*/
pretty_print([[RelType, [tuple, AttrDescription]], Tuples]) :-
(RelType = rel ; RelType = trel),
!,
nl,
max_attr_length(AttrDescription, AttrLength),
write_tuples(AttrDescription, Tuples, AttrLength).
% NVK ADDED NR: Support for nested relations.
pretty_print([[nrel, [tuple, AttrDescription]], Tuples]) :-
nr_pretty_print([[nrel, [tuple, AttrDescription]], Tuples]),
!.
% NVK ADDED NR END
pretty_print(L) :-
write_element(L, 0).
/*
1.1.2 Predicate ~show~
*/
show([Type, Value]) :-
!,
display(Type, Value).
show(Y) :-
write(Y),
pretty_print(Y),
nl.
/*
1.1.3 Predicate ~display~
---- display(Type, Value) :-
----
Display the value according to its type description. To be extended when new
type constructors are added to Secondo.
*/
% Section:Start:display_2_b
% Section:End:display_2_b
display(int, N) :-
!,
write(N).
display(real, N) :-
!,
write(N).
display(bool, N) :-
!,
write(N).
display(string, N) :-
!,
term_to_atom(String, N),
displayString(String).
display(date, N) :-
!,
term_to_atom(String, N),
displayString(String).
display(instant, N) :-
!,
term_to_atom(String, N),
displayString(String).
display(text, N) :-
!,
write_elements([N], 0).
display(rect, [L, R, B, T]) :-
!,
write('rectangle xl = '), write(L),
write(', xr = '), write(R),
write(', yb = '), write(B),
write(', yt = '), write(T).
display([Rel, [tuple, Attrs]], Tuples) :-
(Rel = rel ; Rel = trel),
!,
nl,
max_attr_length(Attrs, AttrLength),
displayTuples(Attrs, Tuples, AttrLength).
% NVK ADDED NR: Support for nested relations.
display([Rel, [tuple, Attrs]], Tuples) :-
nr_display([Rel, [tuple, Attrs]], Tuples),
!.
% Just write the terms to stdout to avoid the 'There is no specific display'
% message.
display(upoint, UPoint) :-
write_term(UPoint, []),
!.
display(mpoint, MPoint) :-
write_element(MPoint, 0),
!.
% NVK ADDED END
display(duration, [0, MSec]) :-
MSec > 3600000,
!,
Hour is round(float_integer_part(MSec / 3600000.0)),
write(Hour), write('h '),
Rest is MSec - (Hour * 3600000),
display(duration, [0, Rest]).
display(duration, [0, MSec]) :-
MSec > 60000,
!,
Min is round(float_integer_part(MSec / 60000.0)),
write(Min), write('min '),
Rest is MSec - (Min * 60000),
display(duration, [0, Rest]).
display(duration, [0, MSec]) :-
MSec > 1000,
!,
Sec is round(float_integer_part(MSec / 1000.0)),
write(Sec), write('s '),
Rest is MSec - (Sec * 1000),
display(duration, [0, Rest]).
display(duration, [0, MSec]) :-
!,
MS is round(MSec),
write(MS), write('ms').
display(duration, [Days, MSec]) :-
!,
write(Days), write('d '),
display(duration, [0, MSec]).
display(Type, Value) :-
write('There is no specific display function for type '), write(Type),
write('. '),
nl,
write('Generic display used. '),
nl,
pretty_print(Value),
nl.
displayString([]).
displayString([Char | Rest]) :-
put(Char),
displayString(Rest).
displayTuples(_, [], _).
displayTuples(Attrs, [Tuple | Rest], AttrLength) :-
displayTuple(Attrs, Tuple, AttrLength),
nl,
displayTuples(Attrs, Rest, AttrLength).
displayTuple([], _, _).
displayTuple([[Name, Type] | Attrs], [Value | Values], AttrNameLength) :-
atom_length(Name, NLength),
PadLength is AttrNameLength - NLength,
write_spaces(PadLength),
write(Name),
write(' : '),
display(Type, Value),
nl,
displayTuple(Attrs, Values, AttrNameLength).
/*
1.2 Predicate ~secondo~
Predicate ~secondo~ expects its argument to be a string atom or
a nested list, representing a query to the SECONDO system. The query is
executed and the result pretty-printed. If the query fails, the error code
and error message are printed.
---- secondo(+SecondoExecutableExpression)
----
Send ~SecondoExecutableExpression~ to the Secondo kernel (using secondo/2) and
print the returned result onto the screen.
Keep the optimizer informed by tracking 'open', 'close', 'restore', 'let' and
'delete' commands within ~SecondoExecutableExpression~.
---- secondo_direct(+SecondoExecutableExpression)
----
Send ~SecondoExecutableExpression~ to the Secondo kernel (using secondo/2) and
print the returned result onto the screen.
Do NOT keep the optimizer informed by tracking 'open', 'close', 'rstore',
'let' or 'delete' commands within ~SecondoExecutableExpression~.
This variant is useful within automaically triggered queries to secondo, e.g.
deleting or creating objects used by the optimizer (like samples, indexes, small
objects). This command should never be used by the user!
*/
% Such facts are used to mark a file has been considered by some predicate:
:- dynamic(tempConsideredFile/1).
% atom_postfix(+Atom, +PrefixLength, ?Post)
% succeeds iff Post is a postfix of Atom starting after PrefixLength
atom_postfix(Atom, PrefixLength, Post) :-
atom_length(Atom, Length),
PostLength is Length - PrefixLength,
sub_atom(Atom, PrefixLength, PostLength, 0, Post).
/*
Some facts which store important state information
---- databaseName(X)
----
When a database X gets openend, a fact databaseName(X) gets asserted.
If no such fact exists, no database is opened. The fact is used to get the name
of the currently opened database.
*/
:- assert(helpLine(secondo,1,
[[+,'CommandString',
'Command to send as a string (enclose in single quotes).']],
'Send a command to the DBMS kernel.')).
:- dynamic databaseName/1.
promptSecondoResultSucceeded(Result) :-
write('Command succeeded, result:'),
nl, nl,
show(Result), !.
promptSecondoResultFailed :-
secondo_error_info(ErrorCode, ErrorString),
write('Command failed with error code : '),
write(ErrorCode), nl,
write('and error message : '), nl,
write(ErrorString), nl, !.
secondo(X) :-
sub_atom(X,0,_,_,'open '),
atom_postfix(X, 14, DB1),
downcase_atom(DB1, DB), !,
( secondo(X, Y)
*-> ( promptSecondoResultSucceeded(Y), !,
retractall(databaseName(_)),
assert(databaseName(DB)),
readSystemIdentifiers,
readSecondoTypeSizes,
refreshSecondoCatalogInfo,
checkObjectNamingConvention,
updateCatalog,
updateCatalog
% ,ensureSmallObjectsExist
)
; ( promptSecondoResultFailed,
fail
)
), !.
secondo(X) :-
sub_atom(X,0,_,_,'close'), !,
( secondo(X, Y)
*-> ( promptSecondoResultSucceeded(Y),
retractall(databaseName(_))
)
; ( promptSecondoResultFailed,
fail
)
), !.
secondo(X) :-
sub_atom(X,0,6,_,'update '),
isDatabaseOpen, !,
( secondo(X, Y)
*-> promptSecondoResultSucceeded(Y)
; ( promptSecondoResultFailed,
fail
)
), !.
secondo(X) :-
member(Command,['let ', 'derive ', 'delete ']),
sub_atom(X,0,CommandLength,_,Command),
( notIsDatabaseOpen
-> ( write('\nCannot execute command, because no database is open.\n'),
!, fail
)
; true
),
( member(Command,['let ', 'derive ']) % if this is a let/derive command,
-> ( % we need to test, whether the (downcased) objectname is not
% already used in the DB and the name is a valid itentifier
sub_atom(X,PosEq,1,_,'='),
Namelength is PosEq - CommandLength, !,
sub_atom(X,CommandLength,Namelength,_,ExtObjNameA),
removeWhitespace(ExtObjNameA,ExtObjName),
dcName2externalName(DCobjName,ExtObjName),
( secondoCatalogInfo(DCobjName,ExtOther,_,_) % already used?
-> ( write_list(['\nERROR:\tCannot create object \'',
ExtObjName,'\'.\n','--->\tThere already ',
'exits an object named \'',ExtOther,'\'!\n']),
nl,
!, fail
)
; ( validIdentifier(ExtObjName) % identifier valid?
-> true
; ( write_list(['\nERROR:\tCannot create object \'',
ExtObjName,'\'.\n',
'--->\tInvalid identifier!\n']),
nl,
!, fail
)
)
)
)
; true % if this is a delete command
),
( secondo(X, Y)
*-> ( promptSecondoResultSucceeded(Y),
updateCatalog,
updateCatalog
% ,ensureSmallObjectsExist
% ,ensureSamplesExist
)
; ( promptSecondoResultFailed,
fail
)
),
!.
secondo(X) :-
sub_atom(X,0,_,_,'create '),
not(my_concat_atom([create, database, _], ' ', X)),
isDatabaseOpen,
( secondo(X, Y)
*-> promptSecondoResultSucceeded(Y)
; ( promptSecondoResultFailed,
fail
)
), !.
% restore database
% One should consider wiping out the knowledge base on the target database!
secondo(X) :-
my_concat_atom([restore, database, DB1, from, _], ' ', X),
( notIsDatabaseOpen
-> ( downcase_atom(DB1, DB), !,
( secondo(X, Y)
*-> ( promptSecondoResultSucceeded(Y),
retractall(databaseName(_)),
assert(databaseName(DB)),
readSystemIdentifiers
)
; ( promptSecondoResultFailed,
fail
)
)
)
; write('\nERROR:\tCannot restore database, because a database is open.\n')
),
updateCatalog,
updateCatalog,
% ensureSmallObjectsExist,
!.
% restore object
secondo(X) :-
my_concat_atom([restore, _, from, _], ' ', X),
( isDatabaseOpen
-> write('\nERROR:\tCannot restore object, because no database is open.\n')
; ( secondo(X, Y)
*-> ( promptSecondoResultSucceeded(Y)
)
; ( promptSecondoResultFailed,
fail
)
)
),
updateCatalog,
updateCatalog,
% ensureSmallObjectsExist,
!.
secondo(X) :-
my_concat_atom([list, objects],' ',X),
isDatabaseOpen,
secondo(X, Y),
promptSecondoResultSucceeded(Y), !.
secondo(X) :-
sub_atom(X,0,_,_,'query'),
isDatabaseOpen, !,
( secondo(X, Y)
*-> ( promptSecondoResultSucceeded(Y), !
)
; ( promptSecondoResultFailed,
fail
)
), !.
% fallback-case (all other commands)
secondo(X) :-
( secondo(X, Y)
*-> ( promptSecondoResultSucceeded(Y), !)
; ( promptSecondoResultFailed,
fail
)
), !.
% Variant of execulting a command on the Secondo kernel
% without updating the internal optimizer knowledge base.
% Not to be used by the user!
secondo_direct(X) :-
( secondo(X, Y)
*-> ( promptSecondoResultSucceeded(Y), !)
; ( promptSecondoResultFailed,
fail
)
), !.
/*
1.4 Operators ~query~, ~update~, ~let~, ~create~, ~open~, ~restore~ and ~delete~
The purpose of these operators is to make using the PROLOG interface
similar to using SecondoTTY. A SecondoTTY query
---- query ten
----
can be issued as
---- query 'ten'.
----
in the PROLOG interface via the ~query~ operator. The operators
~delete~, ~let~, ~create~, ~open~, and ~update~ work the same way.
*/
:- assert(helpLine(let,1,
[[+,'ExecQuery','Partial command in Secondo syntax.']],
'Prepend \'query \' and send to DBMS-kernel.')).
:- assert(helpLine(query,1,
[[+,'ExecQuery','Partial command in Secondo syntax.']],
'Prepend \'query \' and send to DBMS-kernel.')).
:- assert(helpLine(derive,1,
[[+,'ExecQuery','Partial command in Secondo syntax.']],
'Prepend \'derive \' and send to DBMS-kernel.')).
:- assert(helpLine(create,1,
[[+,'ExecQuery','Partial command in Secondo syntax.']],
'Prepend \'create \' and send to DBMS-kernel.')).
:- assert(helpLine(update,1,
[[+,'ExecQuery','Partial command in Secondo syntax.']],
'Prepend \'update \' and send to DBMS-kernel.')).
:- assert(helpLine(delete,1,
[[+,'ExecQuery','Partial command in Secondo syntax.']],
'Prepend \'delete \' and send to DBMS-kernel.')).
:- assert(helpLine(open,1,
[[+,'ExecQuery','Partial command in Secondo syntax.']],
'Prepend \'open \' and send to DBMS-kernel.')).
:- assert(helpLine(restore,1,
[[+,'ExecQuery','Partial command in Secondo syntax.']],
'Prepend \'restore \' and send to DBMS-kernel.')).
:- op(993, fx, open).
:- op(993, fx, restore).
:- op(959, fx, database).
%:- op(960, xfx, from). % already defined in file optimizer.pl
:- op(993, fx, query).
:- op(993, fx, delete).
:- op(993, fx, let).
:- op(993, fx, create).
:- op(993, fx, derive).
:- op(993, fx, update).
isDatabaseOpen :-
( databaseName(_)
-> true
; ( write('No database open.'), nl, fail)
), !.
notIsDatabaseOpen :-
not(databaseName(_)), !.
query(Query) :-
query(Query, _).
query(Query, Time) :-
isDatabaseOpen,
atom(Query),
atom_concat('query ', Query, QueryText), !,
getTime( secondo(QueryText), Time).
let(Query) :-
isDatabaseOpen,
atom(Query),
my_concat_atom(['let', Query], ' ', QueryText), !,
secondo(QueryText).
derive(Query) :-
isDatabaseOpen,
atom(Query),
atom_concat('derive ', Query, QueryText), !,
secondo(QueryText).
create(Query) :-
atom(Query),
atom_concat('create ', Query, QueryText), !,
secondo(QueryText).
update(Query) :-
isDatabaseOpen,
atom(Query),
atom_concat('update ', Query, QueryText), !,
secondo(QueryText).
delete(Query) :-
atom(Query),
atom_concat('delete ', Query, QueryText), !,
secondo(QueryText).
% more comfortable (without quoting)
open(Query) :-
notIsDatabaseOpen,
Query =.. [database, DB],
atom(DB),
atom_concat('open database ', DB, QueryText), !,
secondo(QueryText),
dropTempRels.
% the hard way...
open(Query) :-
notIsDatabaseOpen,
atom(Query),
atom_concat('open ', Query, QueryText), !,
secondo(QueryText),
dropTempRels.
% the hard way...
restore(Query) :-
notIsDatabaseOpen,
atom(Query),
atom_concat('restore ', Query, QueryText), !,
secondo(QueryText).
% more comfortable (without quoting)
restore(Query) :-
Query =.. [from,Obj,Source],
( ( atom(Source), Obj =.. [database, DB], atom(DB) ) % restore database
-> ( notIsDatabaseOpen
-> my_concat_atom(['restore database',DB,'from',Source],' ',QueryText)
; ( write_list(['\nERROR:\tCannot restore a database, \n',
'--->\twhile a database is open!']), nl,
!, fail
)
)
; ( ( atom(Obj), term_to_atom(Source, SourceA) ) % restore object
-> ( notIsDatabaseOpen
-> (write_list(['\nERROR:\tCannot restore object.\n',
'--->\tNo database open.']), nl, !, fail)
; my_concat_atom(['restore ',Obj,'from',SourceA],' ',QueryText)
)
; ( write_list(['\nERROR:\tInvalid restore command.\n',
'\tThe correct syntax is \'restore <objname> from <file>.\'',
'\n\tor \'restore database <dbname> from <file>.\'.']), nl,
!, fail
)
)
),
secondo(QueryText).
/*
The keywords open and close are already assigned with operations
on streams. Hence we provide ~openDB~ and closeDB to close a database.
*/
:-assert(helpLine(cdb,0,[],'Close current database.')).
:-assert(helpLine(closeDB,0,[],'Close current database.')).
cdb :- closeDB.
closedb :- closeDB.
closeDB :-
secondo('close database').
odb(Name) :- openDB(Name).
openDB(Name) :-
atom_concat('open database ', Name, Cmd),
secondo(Cmd),
dropTempRels.
:-assert(helpLine(ldb,0,[],'List available databases.')).
:-assert(helpLine(listDB,0,[],'List available databases.')).
ldb :- listDB.
listDB :-
secondo('list databases').
:-assert(helpLine(lo,0,[],'Send \'list objects\'.')).
:-assert(helpLine(listObj,0,[],'Send \'list objects\'.')).
lo :- listObj.
listObj :-
secondo('list objects').
% search for a description of operator O
:- assert(helpLine(findop,1,
[[+,'OperatorName','The name of the operator to query for.']],
'Show help on a given Secondo operator.')).
findop(O) :-
my_concat_atom([ 'query SEC2OPERATORINFO feed filter[.Name contains "',
O, '"] consume' ], Q),
runQuery(Q).
% dump the command history to a given file name
:- assert(helpLine(cmdHist2File,1,
[[+,'FileName','The file used for storing the history.']],
'Dump the command history to a file.')).
cmdHist2File(Name) :-
my_concat_atom(['query SEC2COMMANDS feed '], Q),
dumpQueryResult2File(Q, Name, Q2),
runQuery(Q2).
% dump the result of a secondo query to a CSV file
dumpQueryResult2File(Q, File, Q2) :-
my_concat_atom([Q, ' dumpstream["', File, '","|"] tconsume'], Q2).
% removing whitespace (tab, space) from an atomic
removeWhitespace(ExtObjNameA,ExtObjName) :-
atom_chars(ExtObjNameA,CharListDirty),
delete(CharListDirty,' ',CharListDirty1),
delete(CharListDirty1,'\t',CharListCleaned),
atom_chars(ExtObjName,CharListCleaned),
!.
/*
Useful for debugging
*/
showValue(Name, Var) :-
write(Name), write(': '), write(Var), nl, nl.
mark(X) :-
write('(* Mark '), write(X), write(' *)'), nl.
/*
2.1 Generic display for printing formatted tables
Sometimes we want to collect some information and to print it
as a table, e.g. predicate ~writeSizes/0~. Below there are some
predicates which display lists of well defined tuples as specified
by a header list. If the data is presented in a prolog list
as [t1, t2, ... tn] and ti are itself prolog lists of fixed length
each value will be printed in a separate column. Example application:
----
findall(X, createMyTuples(_, X), L ),
TupFormat = [ ['Size', 'c'],
['Time', 'l'],
['Error', 'l'] ],
showTuples(L, TupFormat).
----
*/
showTuples(L, TupFormat) :-
nl, nl,
showHeader(TupFormat, WriteSpec),
showTuplesRec(L, WriteSpec).
showTuplesRec([], _).
showTuplesRec([H|T], WriteSpec) :-
showTupleRec(H, WriteSpec), nl,
%format('~w~t~+~w~t~+~w~t~+~w~n',H),
showTuplesRec(T, WriteSpec).
showTupleRec([], _).
showTupleRec([H|T], [Wh|Wt]) :-
%showValue('Wh', Wh),
writef(Wh, [H]),
%format('~w~t ~+~w~t ~+~w~t~ +~w',[H]),
showTupleRec(T, Wt).
showHeader(L, WriteSpec) :-
showHeaderRec(L, [], HeadList, [], WriteSpec, 0, Len),
showTuplesRec([HeadList], WriteSpec),
Len2 is Len + 2,
writef('%r', ['-', Len2]), nl.
showHeaderRec([], L1, L1, L2, L2, N, N).
showHeaderRec([H|T], Tmp1, Res1, Tmp2, Res2, Tmp3, Res3 ) :-
H = [Attr, Adjust],
atom_length(Attr, Len),
FieldLen is Len + 4,
TotalLen is Tmp3 + FieldLen,
my_concat_atom([' %', FieldLen, Adjust], WriteSpec),
append(Tmp1, [Attr], L1),
append(Tmp2, [WriteSpec], L2),
showHeaderRec(T, L1, Res1, L2, Res2, TotalLen, Res3 ).
/*
Write a list of tuples to a file. The members of an inner
list are separated by a comma.
*/
writeElem(FD, []) :-
write(FD, '\n').
writeElem(FD, [H | T]) :-
write(FD, H),
( length(T, 0) -> write(FD, ' ')
; write(FD, ', ') ),
writeElem(FD, T).
dumpTuples2File(Name, T, Format) :-
project(1, Format, Fp),
append([Fp], T, L),
showValue('L:', L),
open(Name, write, FD),
checklist( writeElem(FD), L),
close(FD).
/*
Extract the N-th element out of all tuples given in list
L and unify them with R.
*/
project(N, L, R) :-
maplist(nth1(N), L, R).
/*
A predicate which translates the first letter of an atom to
lower case.
*/
downcase_first(Atom, Res) :-
atom_chars(Atom, [H | T]),
downcase_atom(H, Hdown),
append([Hdown], T, L),
name(Res, L).
/*
2.3 ~subList/3~
----
subList(+L, +N, ?Res)
----
Unifies the first ~N~ elements of List ~L~ with ~Res~.
*/
subList(L, N, Res) :-
subListRec(L, N, 1, Res).
subListRec([H|_], N, N, [H]).
subListRec([H|T], N, Pos, [H|T2]) :-
NewPos is Pos + 1,
subListRec(T, N, NewPos, T2).
/*
2.4 Runtime Flags
the dynamic predicate ~flag~ a tool for setting and querying options.
This is useful to set global options.
*/
:- dynamic flag/2,
clearflags.
clearflags :-
retractall( flag(_,_) ).
setflag(F) :- assert( flag(F, on) ).
clearflag(F) :- retractall( flag(F, _) ).
showflag( [F, Val], _ ) :-
nl, write(F), write(' --> '), write(Val), nl.
showflags :-
findall( [X, Y], flag(X, Y), L),
maplist( showflag, L, _).
/*
2.5 Running Queries
The clause ~runQuery~ can be used to execute or just print queries
depending on the flag ~printQueryOnlyMode~.
*/
showQuery(Q) :-
nl, write(Q), nl.
runQuery(Q) :-
( flag(printQueryOnlyMode, on)
-> ( showQuery(Q)
)
; ( nl, write('Executing '), write(Q), write(' ...'), nl, secondo(Q)
)
), !.
runQuery(Q, Res) :-
( flag(printQueryOnlyMode, on)
-> ( showQuery(Q),
Res = 999,
nl, write('Dummy-Result: '), write(Res), nl
)
; ( nl, write('Executing '), write(Q), write(' ...'), nl,
secondo(Q, [_, Res]),
nl, write('Result: '), write(Res), nl
)
), !.
/*
3.0 Stop Watch Predicate
---- time(+Clause)
----
This predicate stops the time required to answer query ~Clause~ and prints the
needed time on screen.
*/
time(Clause) :-
get_time(Time1),
(call(Clause) ; true),
get_time(Time2),
Time is Time2 - Time1,
my_convert_time(Time, _, _, _, _, Minute, Sec, MilliSec),
MSs is Minute *60000 + Sec*1000 + MilliSec,
write('Elapsed Time: '),
write(MSs),
write(' ms'),nl.
/*
End of file ~auxiliary.pl~
*/