This commit is contained in:
duboissim 2024-03-15 23:19:57 +01:00
parent 1ce0b1db2f
commit cac813cfc7
1 changed files with 55 additions and 13 deletions

View File

@ -2,6 +2,25 @@
* Authors: * Authors:
* Dubois Brieuc * Dubois Brieuc
* Dubois Simon * Dubois Simon
*
* Known Limitation and problems:
* Currently a condtion in a query as to contain no space in order to function properly
* Ex: the condtion +name="Dakota" will work but the conditions +name = "Dakota"
* or +name="North Dakota" will not. This is due to the way we parse the query. We did it
* with split_string. We were not able to use the prolog_term predicate given to us.
*
* SQL test:
* Test 10 failed because instead of returning [+<atom>, +<atom>] for the column name
* we return [<atom>, <atom>] because that's how we store the column names after an insert
*
* Test 12 and 21:
* When we return row of an empty table instead of having [] we have [_] same thing happens after
* we drop a table.
*
* DCG test:
* Test 5 failed:
* We don't cover the case where the number of values inserted isn't the same as the number of columns
* in the table.
*/ */
:- dynamic tables/0. :- dynamic tables/0.
@ -159,7 +178,9 @@ delete(_, _).
does_match([], _, _) :- !. does_match([], _, _) :- !.
/**
* fails if conditons isn't respected in row
*/
does_match([Cond|Rest], Table, Row) :- does_match([Cond|Rest], Table, Row) :-
% Extract the operator, field and value from the condition % Extract the operator, field and value from the condition
Cond =.. [Operator | T], Cond =.. [Operator | T],
@ -222,13 +243,17 @@ selec(Table, _, _, _) :-
!. !.
selec(Table, Selector, Cond, Projection) :- selec(Table, Selector, Cond, Projection) :-
%fetch columns names and all rows of Table
tabl(Table, Cols), tabl(Table, Cols),
row(Table, R), row(Table, R),
%remove rows that don't respect the conditions
does_match(Cond, Table, R), does_match(Cond, Table, R),
%reduce result to only selected columns
selector(R,Cols, Selector, [],[],ColumnNames,ColumnValue), selector(R,Cols, Selector, [],[],ColumnNames,ColumnValue),
%reorder result to match query order
reverse(ColumnNames, Names), reverse(ColumnNames, Names),
reverse(ColumnValue, Values), reverse(ColumnValue, Values),
%unify the lists to projection
Projection = Names/Values. Projection = Names/Values.
selec(Table, *, Cond, Projection) :- selec(Table, *, Cond, Projection) :-
@ -238,17 +263,18 @@ selec(Table, *, Cond, Projection) :-
Projection = Cols/R. Projection = Cols/R.
/** /**
* Row: A row from the table * +Row: A row from the table
* Cols: name of the column of the table * +Cols: name of the column of the table
* [Selector|Selectors] name(s) of the column(s) for selection * +[Selector|Selectors] name(s) of the column(s) for selection
* AccCols: acumulator list for the column(s) name(s) * +AccCols: acumulator list for the column(s) name(s)
* AccVals: acumulator list for the row(s) values * +AccVals: acumulator list for the row(s) values
* ColumnNames: List returning the column(s) name(s) * -ColumnNames: List returning the column(s) name(s)
* ColumnValue: List returning the row values for each column * -ColumnValue: List returning the row values for each column
* *
* This predicate return * This predicate return
*/ */
%base case
selector(_,_,[],ColumnNames, ColumnValue, ColumnNames, ColumnValue):-!. selector(_,_,[],ColumnNames, ColumnValue, ColumnNames, ColumnValue):-!.
selector(Row, Cols, [+Selector|Selectors], AccCols, AccVals, ColumnNames, ColumnValue):- selector(Row, Cols, [+Selector|Selectors], AccCols, AccVals, ColumnNames, ColumnValue):-
@ -256,7 +282,7 @@ selector(Row, Cols, [+Selector|Selectors], AccCols, AccVals, ColumnNames, Column
%find the value corresponding to the column in the row %find the value corresponding to the column in the row
nth0(Index, Cols, Selector), nth0(Index, Cols, Selector),
nth0(Index, Row, Value), nth0(Index, Row, Value),
%go to next column tho evaluate %go to next column tho evaluate and store value and corresponging name
selector(Row, Cols, Selectors, [Selector|AccCols], [Value|AccVals], ColumnNames, ColumnValue) selector(Row, Cols, Selectors, [Selector|AccCols], [Value|AccVals], ColumnNames, ColumnValue)
; ;
string_concat(Selector, " isn't a column of table ", Error), string_concat(Selector, " isn't a column of table ", Error),
@ -299,9 +325,7 @@ ble names are atoms, while column names should follow the format out-
lined before (+<atom>). <cond>denotes a Prolog goal, in Prolog syntax lined before (+<atom>). <cond>denotes a Prolog goal, in Prolog syntax
following the same format as the possible values of items of the Conds following the same format as the possible values of items of the Conds
list passed to selec and delete. list passed to selec and delete.
<value>denotes a prolog value that can be stored into a row. You do <value>denotes a prolog value that can be stored into a row.
not need to handle parsing Prolog (<cond>and <value>) by yourself,
well show how to do it below.
The semantics of this predicate is that of the SQL-predicate contained in The semantics of this predicate is that of the SQL-predicate contained in
the Query string. the Query string.
A SELECT query maps to the selec predicate, while an INSERT A SELECT query maps to the selec predicate, while an INSERT
@ -333,24 +357,32 @@ query(Query, Result):-
apply(Fun, Args), apply(Fun, Args),
last(Args, Result). last(Args, Result).
/**
* For all parse_query on Query must be initiated
*/
/** /**
* Parse SELECT * FROM <table> WHERE <conds> * Parse SELECT * FROM <table> WHERE <conds>
*/ */
parse_query(Query, selec, [AtomTable, *, AtomsConds, R]):- parse_query(Query, selec, [AtomTable, *, AtomsConds, R]):-
%split the query
split_string(Query, " ", ",;+", SplitQuery), split_string(Query, " ", ",;+", SplitQuery),
append(["SELECT"], L1, SplitQuery), append(["SELECT"], L1, SplitQuery),
append(["*"], ["FROM"|L2], L1), append(["*"], ["FROM"|L2], L1),
append([Table], ["WHERE"|Conds],L2), append([Table], ["WHERE"|Conds],L2),
%cast into correct type
atom_string(AtomTable, Table), atom_string(AtomTable, Table),
maplist(parse_cond, AtomsConds, Conds),!. maplist(parse_cond, AtomsConds, Conds),!.
/** /**
* Parse SELECT <cols> FROM <table> WHERE <conds> * Parse SELECT <cols> FROM <table> WHERE <conds>
*/ */
parse_query(Query, selec, [AtomTable, AtomsSelectors, AtomsConds, R]):- parse_query(Query, selec, [AtomTable, AtomsSelectors, AtomsConds, R]):-
%split the query
split_string(Query, " ", ",;+", SplitQuery), split_string(Query, " ", ",;+", SplitQuery),
append(["SELECT"], L1, SplitQuery), append(["SELECT"], L1, SplitQuery),
append(Selectors, ["FROM"|L2], L1), append(Selectors, ["FROM"|L2], L1),
append([Table], ["WHERE"|Conds],L2), append([Table], ["WHERE"|Conds],L2),
%cast into correct type
atom_string(AtomTable, Table), atom_string(AtomTable, Table),
maplist(atom_string, AtomsSelectors1, Selectors), maplist(atom_string, AtomsSelectors1, Selectors),
maplist(add_plus, AtomsSelectors, AtomsSelectors1), maplist(add_plus, AtomsSelectors, AtomsSelectors1),
@ -360,9 +392,11 @@ parse_query(Query, selec, [AtomTable, AtomsSelectors, AtomsConds, R]):-
* Parse SELECT * FROM <table> * Parse SELECT * FROM <table>
*/ */
parse_query(Query, selec, [AtomTable, *, R]):- parse_query(Query, selec, [AtomTable, *, R]):-
%split the query
split_string(Query, " ", ",;+", SplitQuery), split_string(Query, " ", ",;+", SplitQuery),
append(["SELECT"], L1, SplitQuery), append(["SELECT"], L1, SplitQuery),
append(["*"], ["FROM",Table], L1), append(["*"], ["FROM",Table], L1),
%cast into correct type
atom_string(AtomTable, Table), atom_string(AtomTable, Table),
maplist(parse_cond, AtomsConds, Conds),!. maplist(parse_cond, AtomsConds, Conds),!.
@ -370,23 +404,31 @@ parse_query(Query, selec, [AtomTable, *, R]):-
* Parse SELECT <cols> FROM <table> * Parse SELECT <cols> FROM <table>
*/ */
parse_query(Query, selec, [AtomTable, AtomsSelectors, R]):- parse_query(Query, selec, [AtomTable, AtomsSelectors, R]):-
%split the query
split_string(Query, " ", ",;+", SplitQuery), split_string(Query, " ", ",;+", SplitQuery),
append(["SELECT"], L1, SplitQuery), append(["SELECT"], L1, SplitQuery),
append(Selectors, ["FROM",Table], L1), append(Selectors, ["FROM",Table], L1),
%cast into correct type
atom_string(AtomTable, Table), atom_string(AtomTable, Table),
maplist(atom_string, AtomsSelectors1, Selectors), maplist(atom_string, AtomsSelectors1, Selectors),
maplist(add_plus, AtomsSelectors, AtomsSelectors1). maplist(add_plus, AtomsSelectors, AtomsSelectors1).
parse_query(Query, insert, [AtomTable, Values]):- parse_query(Query, insert, [AtomTable, Values]):-
%split the query
split_string(Query, " ", '",();', SplitQuery), split_string(Query, " ", '",();', SplitQuery),
append(["INSERT", "INTO"], L1, SplitQuery), append(["INSERT", "INTO"], L1, SplitQuery),
L1 = [Table | L2], L1 = [Table | L2],
append(_, ["VALUES"|Values1], L2), append(_, ["VALUES"|Values1], L2),
%cast into correct type
maplist(is_number, Values, Values1), maplist(is_number, Values, Values1),
atom_string(AtomTable, Table). atom_string(AtomTable, Table).
add_plus(+A, A). add_plus(+A, A).
/**
* For all parse_cond only Cond must be initiated
*/
% parse >= conditon % parse >= conditon
parse_cond(+AtomLeft>=AtomRight, Cond):- parse_cond(+AtomLeft>=AtomRight, Cond):-
string_chars(Cond, Code), string_chars(Cond, Code),