diff --git a/solution.pl b/solution.pl index 76b7af9..d8ef515 100644 --- a/solution.pl +++ b/solution.pl @@ -1,3 +1,25 @@ +:- use_module(library(dcg/basics)). +% DCG rule that checks if the remainder of the input +% starts with Delim (a list), but does not consume +% any input. +lookahead(Delim , L, L) :- + prefix(Delim , L). +% Checks if the remainder of the input starts with one +% of the items in the supplied list (as per lookahead /3). +lookaheads([H|T]) --> + lookahead(H), ! ; lookaheads(T). +% Reads text until one of the delimiters in Delims is +% encountered , then unifies R with the Prolog term parsed +% from the text. +% ! Will crash the parse if a delimiter is encountered +% but the intervening text is not a Prolog term (you +% don’t have this handle this case). +prolog_term(R, Delims) --> + string(S), lookaheads(Delims), !, { + read_term_from_atom(S, R, []) }. + + + :- dynamic tables/0. /* Prints the names of all existing tables, one per line (use writeln/1). @@ -164,7 +186,86 @@ For example: findall(Values, selec(persons,[+id,+first],[],Values), Projections) returns: Projections = [[0, "Jeffrey"], [1, "Lorena"], [2, "Joseph"], ... */ -/* selec(Table, Selectors, Conds, Projection). */ +selec(Table, Selectors, Conds, Projection) :- + selec_help(Table, Selectors,[], [], ColumnNames, ColumnValue), + %remove combinations that don't exist + row(Table, Row), + has_value(ColumnValue, Row), + Projection = ColumnNames/ColumnValue. + +%base case +selec_help(_, [], ColumnNames, ColumnValue, ColumnNames, ColumnValue). +/** + * Table: name of the table the selection is done one + * [Selector|Selectors] name(s) of the column(s) for selection + * AccCols: acumulator list for the column(s) name(s) + * AccVals: acumulator list for the row(s) values + * ColumnNames: List returning the column(s) name(s) + * ColumnValue: List returning the row values for each column +*/ +selec_help(Table, [Selector|Selectors], AccCols, AccVals, ColumnNames, ColumnValue) :- + %check if table exist + (tabl(Table, Cols) -> + %check if column exist + member(Selector, Cols) -> + %find the value corresponding to the column in the row + nth0(Index, Cols, Selector), + row(Table, Row), + nth0(Index, Row, Value), + %go to next column tho evaluate + selec_help(Table, Selectors, [Selector|AccCols], [Value|AccVals], ColumnNames, ColumnValue) + ; + string_concat(Selector, " isn't a column of table ", X), + string_concat(X, Table, Error), + throw(Error) + ; + string_concat(Table, " doesn't exist.", Error), throw(Error) + ). +/* +Check if a list has all the values in [Value|Rest] +*/ +has_value([], _) :- !. +has_value([Value|Rest], List) :- + memberchk(Value, List), + has_value(Rest, List). + +evaluate_condition_string(ConditionString) :- + atom_codes(AtomCondition, ConditionString), % Convert string to atom + read_term_from_codes(AtomCondition, Term, []), % Parse the term + call(Term). % Evaluate the parsed term + +selec_column(Table, Column, Proj) :- + tabl(Table, Cols), + row(Table, Row), + nth0(I, Cols, Column), + nth0(I, Row, Value), + Proj = Value. + +apply_cond(Table, Cond, Proj) :- + tabl(Table, Cols), + row(Table, Row), + nth0(I, Cols, Column), + nth0(I, Row, Value), + split_string(Cond, " ", "", SubStrings), + Decomp = SubStrings, + Decomp = [Column, Op, Value], + check_condition(Column, Op, Value), + Proj = Row. + +check_condition(Left, =, Right) :- + Left =:= Right. +check_condition(Left, <, Right) :- + Left < Right. +check_condition(Left, >, Right) :- + Left > Right. +check_condition(Left, <=, Right) :- + Left =< Right. +check_condition(Left, >=, Right) :- + Left >= Right. +check_condition(Left, \=, Right) :- + Left =\= Right. + + :- dynamic selec/3. /*