2

This is a follow up question to : Adapting csv reading for multiple tables

If I have the following module defined:

:- module(csv_load_mod,[prepare_db/3]).
:- use_module(library(csv)).
:- set_prolog_stack(global, limit(4*10**9)).

prepare_db(File, Column_Key,Relation) :-
   Column_Key_Term =.. [Column_Key,_],
   Relation_Term =.. [Relation,_,_,_],
   retractall(Column_Key_Term),
   retractall(Relation_Term),
   forall(read_row(File, Row), store_row(Row,Column_Key,Relation)).

store_row(Row,Column_Key,Relation) :-
   Column_Key_Test =.. [Column_Key,ColKeys],
   Row =.. [row|Cols],
   (   call(Column_Key_Test)
   ->  Cols = [RowKey|Values],
       maplist(store_relation(Relation,RowKey), ColKeys, Values)
       ;   ( Cols = [_H|T],
             Column_Key_Term =.. [Column_Key,T],
             assertz(Column_Key_Term)
           )
   ).

store_relation(Relation,RowKey, ColKey, Values) :-
    Relation_Term =.. [Relation,RowKey,ColKey,Values],
    assertz(Relation_Term).

read_row(File, Row) :-
    csv_read_file_row(File, Row, []).

Then I am able to read a table from a csv file.

For example:

:? prepare_db('my_table.csv',mt_col_key, mt_relation).

I would then have a fact mt_col_key([col1,col2,...,coln]) and a set of facts mt_relation/3. But these will be local to the module and would not be exported. I need to use csv_load_mod:mt_relation/3 etc. Is there a way to get a module to export a dynamic predicate or adapt prepare_db/3 so the facts it asserts are not local or they get asserted to the module that called it?

Guy Coder
  • 24,501
  • 8
  • 71
  • 136
user27815
  • 4,767
  • 14
  • 28
  • you should tag this question with [SWI-Prolog], any constructive answer is going to be very specific... anyway, look for [context_module](http://www.swi-prolog.org/pldoc/doc_for?object=context_module/1) in documentation – CapelliC Jul 23 '15 at 14:15

1 Answers1

2

I've simplified the applicative logic, to better illustrate the interesting points. We need 3 things: a module 'driver', i.e. test_csv.pl, the generic loader, i.e. csv_module_test.pl, and at least a file, i.e. file.csv

the driver:

:- module(test_csv, [test_csv/0]).
:- use_module(csv_module_test).

test_csv :-
    context_module(CM),
    prepare_db(CM, 'file.csv').

the loader:

:- module(csv_module_test, [prepare_db/2]).
:- use_module(library(csv)).

prepare_db(CM, File) :-
    forall(csv_read_file_row(File, Row, []), store_row(CM, Row)).

store_row(CM, Row) :-
    Row =.. [row,RelName|Cols],
    Record =.. [RelName|Cols],
    CM:assertz(Record).

test data, file.csv:

key,desc,col1,col2,col3,col4,col5
key_x,desc_x,1,2,3,4,5
key_y,desc_y,10,20,30,40,50

then,

?- test_csv.
true.

?- test_csv:listing.

:- dynamic rel/3.


test_csv :-
    context_module(A),
    prepare_db(A, 'file.csv').

:- dynamic key/1.


:- dynamic key_y/6.

key_y(desc_y, 10, 20, 30, 40, 50).

:- dynamic key_x/6.

key_x(desc_x, 1, 2, 3, 4, 5).

:- dynamic key/6.

key(desc, col1, col2, col3, col4, col5).
true.

that is, relations have been declared as dynamic and asserted in the driver module...

note: the relations' names are fake, since I started with an attempt to follow your applicative logic, and steered to a simplified approach later...

CapelliC
  • 59,646
  • 5
  • 47
  • 90
  • Obviously this does not exactly do what the code in the question did, but it illustrates the point- so thanks :) – user27815 Jul 27 '15 at 09:31