Dynamic Database on Turbo Prolog
Theory
Usually the program is Prologue consists of four main program sections. These include:
-
chapter clauses (offers);
-
chapter predicates (predicates);
-
chapter domains (domains);
-
chapter goal (goals).
Chapter clauses is the heart Prologue-programs; it is in this section that the facts and rules that will operate Prologuewhile trying to resolve the purpose of the program.
Chapter predicates is the section in which the predicates and the domains (types) of their arguments are declared.
Chapter domains serves to declare all non-standard domains we use Prologue.
Chapter goal is the section where you put the target Prologue-programs.
Database
The database predicates in Turbo Prolog are described in the section database, which must appear before the predicates section. All statements with predicates described in database are dynamic database.
The database is called dynamic, since during the operation of the program it (the database) can delete any statements contained in it, as well as add new ones. A dynamic database (DBD) can be written to disk and read from it into RAM. The DDB contains only facts, not rules. In a static database, statements are facts and are part of the program code.
Built-in predicates for working with the database
The following predicates are used to add to the database:
-
asserta(fact) // adding to the beginning of the dbasedom database
-
asserta(fact, dbaseName) // adding to the beginning of the database dbaseName
-
assertz(fact) // adding to the end of the dbasedom database
-
assertz(fact, dbaseName) // adding to the end of the database dbaseName
Loading facts from a file:
-
consult(fileName) // upload to dbasedom database
-
consult(fileName, dbaseName) // load into database dbaseName
Removing a fact:
-
retract(fact) // delete from dbasedom database
-
retract(fact, dbaseName) // delete from database dbaseName
Saving the database in a file:
-
save(fileName) // save database dbasedom in file fileName
-
save(fileName, dbaseName) // saving database dbaseName in file fileName
Program description
The database will contain one table, the T-shirt table, whose columns are listed below:
-
name – name.
-
Price (RUB) — price in rubles.
-
Sex – men’s or women’s T-shirt.
-
Size (International) – The international size of the T-shirt.
-
Size (Europe) — the European size of the T-shirt.
-
color – color.
-
Material – T-shirt material.
-
Production year – the year of production.
The following features of the program are expected:
-
Reading a database from a CSV file
-
Adding a new record to the database;
-
Delete T-shirt by name;
-
Changing a record in the database;
-
T-shirt search by name;
-
Display all T-shirts in the console;
-
Saving the database to a CSV file;
-
Deleting all records from the database;
-
Exit from the program;
Code
At the very beginning there is a description of all domains, databases and predicates used in the program:
Domains
name, world, color, sex, material = string % домены строкового типа
europe, year, price = integer % домены целочисленного типа
file = datafile % домен типа file
arr = string* % массив из строк
integers = integer* % массив из целых чисел
Database
dt_shirt(name, price, sex, world, europe, color, material, year) % описание предиката БД
Predicates
repeat % зацикливает кусок кода
do_mbase % создаёт главное окно программы и вызывает предикат menu
menu % создаёт меню программы
process(integer) % ждет ввода номера функции из меню и затем вызывает её
clear_database % очищение базы данных
error % сообщает об ошибке
read_until_not_integer(integer) % ждет ввода целого числа
write_all % вывод всех футболок в командную строку
write_all(arr,integers,arr,arr,integers,arr,arr,integers) % вывод всех футболок в командную строку
write_all_csv % запись всех футболок в csv файл
write_all_csv(arr,integers,arr,arr,integers,arr,arr,integers) % запись всех футболок в csv файл
read_rows() % считывает строки из csv файла
front_string(string, string, string) % считывание одного значения из csv до разделителя ;
read_prov(integer) % ввод номера функции из меню
find(integer) % вызов предиката поиска в зависимости от введенного числа
find_shirt_name(string) % поиск футболки по имени
find_material(string) % поиск футболки по материалу
find_name(string)
find_mat(string)
A little lower is the Goal section, which contains predicates that are called when the program starts:
Goal
do_mbase. % вызов предиката do_mbase
And finally Clauses. Here I will describe all the rules of the program.
repeat – necessary for looping. Implemented by calling itself:
repeat.
repeat:-repeat.
read_prov – when entering an integer, returns this number, otherwise calls the predicate error:
read_prov(Vibor):-
readint(Vibor);
error,
Vibor = 0,
menu.
Menu
do_mbase – a predicate from which the execution of the program begins. Creates the main window and calls menu.
menu – creates a menu and waits for the user to enter a number from 1 to 9. When entering a number, a predicate is called process, which performs one of nine selected functions:
do_mbase :-
makewindow(1,11,3," T-SHIRTS DATABASE ",0,0,25,80),
menu,
clear_database.
menu :-
repeat, clearwindow,
nl,
write(" ********************************* "),nl,
write(" * 1. Read Database from file * "),nl,
write(" * 2. Add new T-shirt in DB * "),nl,
write(" * 3. Delete T-shirt from DB * "),nl,
write(" * 4. Edit T-shirt in DB * "),nl,
write(" * 5. Find T-shirt * "),nl,
write(" * 6. Show all data * "),nl,
write(" * 7. Write Database to file * "),nl,
write(" * 8. Delete All DB * "),nl,
write(" * 9. Exit * "),nl,
write(" ********************************* "),nl,
write(" Choose number 1-9 : "),
read_prov(Vibor),nl,
process(Vibor),Vibor = 9.
Next, we describe all these functions.
Description of functions
Reading database from csv file
process(1) – creates a window where you can enter the name of the csv file from which we want to read the database. Reading occurs due to the predicate read_rows(). If the database is successfully read, the message “DB successfully read from file.” is displayed. On failure, “Error reading file!” is displayed. Then, in both cases, after pressing the spacebar, it jumps back to the menu.
process(1) :-
makewindow(2,11,3,"Read data from file",2,20,15,40),shiftwindow(2),
write("Input File name (data.csv): "),
readln(Filename),
existfile(Filename),
openread(datafile, Filename),
readdevice(datafile),
read_rows(),
closefile(datafile), readdevice(keyboard),
write("DB successfully read from file."),nl,!,
write("Press space bar"), readchar(_),
removewindow, shiftwindow(1), clearwindow, menu;
write("Error reading file!"), nl, !,
write("Press space bar."),readchar(_),
removewindow, shiftwindow(1), clearwindow, menu, fail.
read_rows() – reads the csv file line by line, using eight calls (we have 8 parameters in the database) of the predicate front_string. After reading each row, inserts the resulting values at the end of the database dt_shirtusing the built-in predicate assertz.
front_string(Line, Param, Tail) — reads the line until it encounters the csv separator – ;
Has 3 options:
-
Line – initial line
-
Param – part of the string before the first delimiter – ;
-
Tail – the remaining line after the delimiter – ;
read_rows() :-not(eof(datafile)),
readln(Line),
front_string(Line, F1_STR, Tail1),
front_string(Tail1, F2_STR, Tail2), str_int(F2_STR, Price),
front_string(Tail2, F3_STR, Tail3),
front_string(Tail3, F4_STR, Tail4),
front_string(Tail4, F5_STR, Tail5), str_int(F5_STR, Europe),
front_string(Tail5, F6_STR, Tail6),
front_string(Tail6, F7_STR, Tail7),
front_string(Tail7, F8_STR, _), str_int(F8_STR, Year),
assertz(dt_shirt(F1_STR,Price,F3_STR,F4_STR,Europe,F6_STR,F7_STR,Year)), !, read_rows();
not(eof(datafile)), !,
write(" ********************************"), nl,
write(" * READING ERROR! * "), nl,
write(" * REMAINING DATA WAS NOT READ! * "), nl,
write(" * SOME MATERIALS ADDED! * "), nl,
write(" ******************************** "), nl; !.
front_string("", "", "") :- !.
front_string(Line, Param, Tail) :-frontchar(Line, LineH, LineT),
LineH = ';', !,
Param = "", Tail = LineT;
frontchar(Line, LineH, LineT),
LineH <> ';', !,
front_string(LineT, T, Tail),
str_char(LineHS, LineH),
concat(LineHS, T, Param).
Adding a new T-shirt to the database
process(2) – creates a window where you can enter the parameters of a new T-shirt. Input of numerical values occurs through a predicate read_until_not_integer. After entering all the parameters, they are inserted at the end of the database dt_shirtusing the built-in predicate assertz.
process(2) :-
makewindow(3,11,3,"Add data",2,20,18,58),shiftwindow(3),
write("Please, Input T-shirt:"),nl,
write("Name: "), readln(Name),
write("Price (RUB): "), read_until_not_integer(Price),
write("Sex: "), readln(Sex),
write("Size (International) : "), readln(World),
write("Size (Europe): "), read_until_not_integer(Europe),
write("Color: "), readln(Color),
write("Material: "), readln(Material),
write("Production year: "), read_until_not_integer(Year),
assertz(dt_shirt(Name,Price,Sex,World,Europe,Color, Material,Year)),
write(Name," added to DB"), nl,!,
write("Press space bar. "), readchar(_),
removewindow, shiftwindow(1), clearwindow, menu.
read_until_not_integer – checks if the entered value is an integer greater than 0 or not. If not, then it is called again.
read_until_not_integer(Integer):-
readint(Integer),
Integer >=0, !;
write("Enter integer number >=0: "),
read_until_not_integer(Integer).
Removing a T-shirt from the database
process(3) – creates a window where you can enter the name of the T-shirt to be deleted. After entering the name of the T-shirt, it is deleted from the database dt_shirtusing the built-in predicate retract.
process(3) :-
makewindow(4,11,3,"Delete data",10,30,7,40),shiftwindow(4),
write("Input T-shirt name: "), readln(Name),
retract(dt_shirt(Name,_,_,_,_,_,_,_)),
write(Name," removed from DB "), nl, !,
write("Press space bar."), readchar(_),
removewindow, shiftwindow(1);
write("No data."),nl,!,
write("Press space bar."),readchar(_),
removewindow, shiftwindow(1).
Change information about a T-shirt
process(4) – creates a window where you can enter the name of the T-shirt, the information about which you want to change. After entering the name of the T-shirt, it is deleted from the database dt_shirtusing the built-in predicate retract. Next, all pairs are introduced
process(4) :-
makewindow(5,11,3,"Edit data",2,20,18,58),shiftwindow(5),
write("Input T-shirt name: "), readln(Name1),
retract(dt_shirt(Name1,_,_,_,_,_,_,_)),
write("Name: "), readln(Name),
write("Price (RUB): "), read_until_not_integer(Price),
write("Sex: "), readln(Sex),
write("Size (International) : "), readln(World),
write("Size (Europe): "), read_until_not_integer(Europe),
write("Color: "), readln(Color),
write("Material: "), readln(Material),
write("Production year: "), read_until_not_integer(Year),
assertz(dt_shirt(Name,Price,Sex,World,Europe,Color, Material,Year)),nl, !,
write("Press space bar."), readchar(_),
removewindow, shiftwindow(1);
write("No data."),nl,!,
write("Press space bar."),readchar(_),
removewindow, shiftwindow(1), clearwindow, menu.
Show all information about the T-shirt
process(5) – creates a window where you can choose how to search for the desired T-shirt: 1 – by name or 2 – by material. Then the predicate is called findwhich searches for a T-shirt by the parameter we have chosen and then displays all the information about it.
process(5) :-
makewindow(6,11,3," Show T-shirt ", 2,30,22,47), shiftwindow(6),
write("1. Find T-shirt by Name "),nl,
write("2. Find T-shirt by Material "),nl,
write(" Choose number 1-2 : "),
read_until_not_integer(N),
N>0,N<3,
find(N),
write("Press space bar"), readchar(_),
removewindow, shiftwindow(1), clearwindow, menu;
write("Wrong input."),nl,!,
write("Press space bar."),readchar(_),
removewindow, shiftwindow(1), clearwindow, menu.
find(1) – it is necessary to enter the name of the T-shirt, information about which we want to receive. After entering the name, the predicate is called find_shirt_nameA that searches the database for a T-shirt. If such a name was found, all information about the T-shirt is displayed in the console. If not, the message “No such T-shirt in database!” is displayed.
find(2) – similar find(1)only now it is necessary to enter the material of the T-shirt we are interested in.
find(1):-clearwindow, write("Input T-shirt name: "), readln(Name),
find_shirt_name(Name), find_name(Name).
find(1):-write("No such T-shirt in database!").
find(2):-clearwindow, write("Input T-shirt material: "), readln(Material),
find_material(Material), find_mat(Material).
find(2):-write("No such T-shirt in database!").
find(_):-write("Error ").
find_shirt_name(Name):-
dt_shirt(Name,Price,Sex,World,Europe,Color, Material,Year),nl,
write(" Name : ",Name),nl,
write(" Price (RUB) : ",Price),nl,
write(" Sex : ",Sex),nl,
write(" Size (International): ",World),nl,
write(" Size (Europe): : ",Europe), nl,
write(" Color : ",Color),nl,
write(" Material : ",Material),nl,
write(" Production year : ",Year),nl, nl, fail.
find_shirt_name(_).
find_material(Material):-
dt_shirt(Name,Price,Sex,World,Europe,Color, Material,Year),nl,
write(" Name : ",Name),nl,
write(" Price (RUB) : ",Price),nl,
write(" Sex : ",Sex),nl,
write(" Size (International): ",World),nl,
write(" Size (Europe): : ",Europe), nl,
write(" Color : ",Color),nl,
write(" Material : ",Material),nl,
write(" Production year : ",Year),nl, nl, fail.
find_material(_).
find_name(Name):-dt_shirt(Name,_,_,_,_,_,_,_).
find_mat(Material):-dt_shirt(_,_,_,_,_,_,Material,_).
Show all records in the database
process(6) – creates a window in which all database records are displayed on the screen. To do this, use the predicate write_all.
process(6) :-
makewindow(7,11,3," Show All data ", 0,0,25,80), shiftwindow(7),
write("Name, Price(Rub), Sex, Size(Inter.), Size(Europe), Color, Material, Year"),
nl,
write("************************************************************************"),
nl,
write_all,
nl,!,
write("Press space bar."),readchar(_),
removewindow, shiftwindow(1), clearwindow, menu;
write("No data."),nl,!,
write("Press space bar."),readchar(_),
removewindow, shiftwindow(1), clearwindow, menu.
write_all() – uses a predicate findall(X,P,L)which collects in the list L all objects X that satisfy the goal P.
write_all([P1|T1], [P2|T2], [P3|T3], [P4|T4], [P5|T5], [P6|T6], [P7|T7], [P8|T8]) – displays all values found in the database separated by commas.
write_all() :-
findall(P1, dt_shirt(P1,_,_, _,_,_,_,_), P1s),
findall(P2, dt_shirt(_,P2,_,_,_,_,_,_ ), P2s),
findall(P3, dt_shirt(_,_,P3, _,_,_,_,_), P3s),
findall(P4, dt_shirt(_,_,_,P4,_,_,_,_ ), P4s),
findall(P5, dt_shirt(_,_,_,_,P5,_,_,_ ), P5s),
findall(P6, dt_shirt(_,_,_,_,_,P6,_,_ ), P6s),
findall(P7, dt_shirt(_,_,_, _,_,_,P7,_), P7s),
findall(P8, dt_shirt(_,_,_, _,_,_,_,P8), P8s),
write_all(P1s, P2s, P3s, P4s, P5s, P6s, P7s, P8s);
writedevice(screen).
write_all([], [], [], [], [], [], [], []) :- !.
write_all([P1|T1], [P2|T2], [P3|T3], [P4|T4], [P5|T5], [P6|T6], [P7|T7], [P8|T8]) :-
write(P1,", ",
P2," (RUB), ",
P3,", ",
P4,", ",
P5,", ",
P6,", ",
P7,", ",
P8),nl,
write("------------------------------------------------------------------------"),nl,
write_all(T1, T2, T3, T4, T5, T6, T7, T8).
Write database to csv file
process(7) – creates a window in which you must enter a file name to save the database. After the recorder is put on the file – writedevice(datafile) and the predicate is called write_all_csvAn that writes the database to a file.
process(7) :-
makewindow(8,11,3," Write Database to file ", 7,30,12,47), shiftwindow(8),
write("Input file name (data.csv): "),
readln(Filename),
existfile(Filename), % Существует ли файл
openwrite(datafile, Filename),
writedevice(datafile),
write_all_csv,
closefile(datafile),
writedevice(screen),
write("DB successfully written to file."),
nl,!,
write("Press space bar."),readchar(_),
removewindow, shiftwindow(1), clearwindow, menu;
write("Error writing file!"),nl,!,
write("Press space bar."),readchar(_),
removewindow, shiftwindow(1), clearwindow, menu.
write_all_csv() – arranged similarly write_all(), but instead of commas, T-shirt parameters are separated by the symbol -;. This is necessary for correct writing to the csv file.
write_all_csv() :-
findall(P1, dt_shirt(P1,_,_, _,_,_,_,_), P1s),
findall(P2, dt_shirt(_,P2,_,_,_,_,_,_ ), P2s),
findall(P3, dt_shirt(_,_,P3, _,_,_,_,_), P3s),
findall(P4, dt_shirt(_,_,_,P4,_,_,_,_ ), P4s),
findall(P5, dt_shirt(_,_,_,_,P5,_,_,_ ), P5s),
findall(P6, dt_shirt(_,_,_,_,_,P6,_,_ ), P6s),
findall(P7, dt_shirt(_,_,_, _,_,_,P7,_), P7s),
findall(P8, dt_shirt(_,_,_, _,_,_,_,P8), P8s),
write_all_csv(P1s, P2s, P3s, P4s, P5s, P6s, P7s, P8s);
writedevice(screen).
write_all_csv([], [], [], [], [], [], [], []) :- !.
write_all_csv([P1|T1], [P2|T2], [P3|T3], [P4|T4], [P5|T5], [P6|T6], [P7|T7], [P8|T8]) :-
write(P1,"; ",
P2,"; ",
P3,"; ",
P4,"; ",
P5,"; ",
P6,"; ",
P7,"; ",
P8),nl,
write_all_csv(T1, T2, T3, T4, T5, T6, T7, T8).
Removing all records from the database
process(8) – creates a window in which, if all records are successfully deleted from the database, the message “DB has been cleared” will be displayed. If an error occurs, “Error writing file!” will be displayed.
process(8) :-
makewindow(9,11,3," Delete All DB ",10,30,7,40), shiftwindow(9),
clear_database,
write("DB has been cleared"),
nl,!,
write("Press space bar."),readchar(_),
removewindow, shiftwindow(1), clearwindow, menu;
write("Error writing file!"),nl,!,
write("Press space bar."),readchar(_),
removewindow, shiftwindow(1), clearwindow, menu.
clear_database – removes all facts from the database using the built-in predicate retract:
clear_database:-
retract(dt_shirt(_,_,_,_,_,_,_,_)),
fail.
clear_database:-!.
Exiting the program
process(9) – clears the database and displays the message “See you again!”.
process(9) :-
clear_database,
write("See you again! "),readchar(_),exit.
End
That’s like all.
I hope you found what you were looking for)
Link to source code: https://github.com/KirillTaE/Dynamic_DataBase_on_TurboProlog