1
votes

I have this module:

:- module(data_db,
          [ attach_data_db/1,           % +File
            current_user_role/2,        % ?User, ?Role
            add_user/2,                 % +User, +Role
            set_user_role/2             % +User, +Role
          ]).
:- use_module(library(persistency)).

:- persistent
        user_role(name:atom, role:oneof([user,administrator])).

attach_data_db(File) :-
        db_attach(File, []).

%%      current_user_role(+Name, -Role) is semidet.

current_user_role(Name, Role) :-
        with_mutex(data_db, user_role(Name, Role)).

add_user(Name, Role) :-
        assert_user_role(Name, Role).

set_user_role(Name, Role) :-
        user_role(Name, Role), !.
set_user_role(Name, Role) :-
        with_mutex(data_db,
                   (  retractall_user_role(Name, _),
                      assert_user_role(Name, Role))).

This is an example from the official documentation. So I can add data to a file with db_attach, but I don't understand how to get the data from the file. The file contains:

created(1603178081.6254506).
assert(user_role('John',user)).
assert(user_role('John',user)).
assert(user_role(han,user)).
1
@peter.cyc: no reason to remove the Prolog tag, as this is while SWI-specific, still Prolog related. - false

1 Answers

3
votes

First you should really ask this question in the SWI-Prolog forum as knowing how to use library(persistency) is not known to many.

One of the nice things about library(persistency) is that it manages the saving and loading of data (facts and predicates) once you have it configured correctly.

Since you gave an example of the file created by library(persistency) I will take it that you have it working correctly.

Your problem is the same one I had when first using library(persistency) in that I expected the facts to be stored in a file the same as if I hand entered them by hand. That is not how you should think of library(persistency), instead think of it as creating a journal of commands and those commands are played back when the journal is opened.

Since it is a journal of commands, this is why you are seeing assert(user_role('John',user)). instead of user_role('John',user).. The command asserts the fact into the Prolog database in memory when the file is opened and played back by library(persistency), this is done automatically by library(persistency).

So to answer your question

How to get data from library(persistency) in SWI-Prolog?

Just access the facts as if they were in the Prolog database, e.g.

?- user_role('John',Role).
Role = user.

While creating a Wiki at the SWI-Prolog forum for using library(persistency) is on my long list, here is the latest complete post with working code I have written.

You will need to click on the triangle to expand the details to see the code.


Here is a complete working example based on your question. There are two Prolog source files, one is used to persist some facts to a journal then halt the Prolog top level to demonstrate that the data is not being passed via the Prolog database but by the journal file. Then a second Prolog source will access the journal file making the facts available at the top level.

File: create_facts.pl

:- module(create_facts,[]).

:- use_module(library(persistency)).

:- persistent
        user_role(name:atom, role:oneof([user,developer,administrator])).

:- db_attach('user.journal', []).

:- initialization(main).

add_user(Name, Role) :-
        (
                user_role(Name, Role), !
        ;
                assert_user_role(Name, Role)
        ).

main :-
    add_user('John',user),
    add_user('Mary',user),
    add_user('Ellen',developer),
    add_user('Stan',user),
    add_user('Eric',administrator).

File: load_facts.pl

:- module(load_facts,[
                user_role/2
        ]).

:- use_module(library(persistency)).

:- persistent
        user_role(name:atom, role:oneof([user,developer,administrator])).

:- db_attach('user.journal', []).

Demonstration

  1. Consult create_facts.pl which will automatically run main creating facts in the journal file.
?- ['create_facts'].
true.
  1. halt the Prolog top level to show that the facts are be passed only in the journal file. Also until halt is executed the journal file may not be complete and will still have a lock on it held by the SWI-Prolog top level.
?- halt.

The journal file created in step 1

File: user.joural

created(1603198849.086677).
assert(user_role('John',user)).
assert(user_role('Mary',user)).
assert(user_role('Ellen',developer)).
assert(user_role('Stan',user)).
assert(user_role('Eric',administrator)).

If you want you can run steps 1 and 2 again and again and it will not duplicate the facts in the journal because

        (
                user_role(Name, Role), !
        ;
                assert_user_role(Name, Role)
        ).

check if the fact exist and if not then asserts the fact into the journal.

  1. Consult load_facts.pl to load the facts from the journal file into the Prolog database.
?- ['load_facts'].
true.
  1. Just access the facts as if they were created normaly
?- user_role(Name,Role).
Name = 'John',
Role = user ;
Name = 'Mary',
Role = user ;
Name = 'Ellen',
Role = developer ;
Name = 'Stan',
Role = user ;
Name = 'Eric',
Role = administrator.

Enjoy!