create solution file
This commit is contained in:
parent
de2fc4afe0
commit
721d974931
|
@ -0,0 +1,188 @@
|
|||
/*
|
||||
Prints the names of all existing tables, one per line (use writeln/1).
|
||||
A table name is always an atom.
|
||||
*/
|
||||
tables.
|
||||
|
||||
:- dynamic tables/1
|
||||
/*
|
||||
Unify Tables with a list of the names of all existing tables.
|
||||
*/
|
||||
tables(Tables).
|
||||
|
||||
:- dynamic table/2
|
||||
/*
|
||||
When this predicate is executed, the effect will be the creation of a new
|
||||
table with the specified list of column names (order matters!).
|
||||
A column name is always an atom.
|
||||
If a table with the given name already exists, the predicate must throw a
|
||||
descriptive exception (use throw/1).
|
||||
All exceptions must have a descriptive error message.
|
||||
*/
|
||||
create table(Table, Cols).
|
||||
|
||||
:- dynamic cols/2
|
||||
/*
|
||||
Unifies Cols with the list of columns for the specified table (in the same
|
||||
order as they were supplied to create table/2).
|
||||
If the given table does not exist, the predicate must throw a descriptive
|
||||
exception (use throw/1).
|
||||
*/
|
||||
cols(Table, Cols).
|
||||
|
||||
:- dynamic row/2
|
||||
/*
|
||||
Unifies Row, one result at a time, with each row in the given Table.
|
||||
If the given table does not exist, the predicate should fail.
|
||||
*/
|
||||
row(Table, Row).
|
||||
|
||||
:- dynamic rows/1
|
||||
/*
|
||||
Displays all rows in the given table, one per line (use writeln/1).
|
||||
If the given table does not exist, the predicate must throw a descriptive
|
||||
exception.
|
||||
*/
|
||||
rows(Table).
|
||||
|
||||
:- dynamic insert/2
|
||||
/*
|
||||
When this predicate is executed, the effect will be the addition of a given
|
||||
row in the given table. The given row is a list of values for each of the
|
||||
corresponding columns in the table (in the order in which the columns
|
||||
were supplied to create table/2).
|
||||
If the given table does not exist, the predicate must throw a descriptive
|
||||
exception.
|
||||
If the row does not have as many elements as the number of columns in
|
||||
the table, the predicate must throw a descriptive exception.
|
||||
*/
|
||||
insert(Table, Row).
|
||||
|
||||
:- dynamic drop/1
|
||||
/*
|
||||
When this predicate is executed, the effect will be the deletion of the given
|
||||
table.
|
||||
Do make sure that all of its rows are deleted as well, so that they don’t
|
||||
magically reappear again if you would recreate a table with the same name
|
||||
and signature later on.
|
||||
If the given table does not exist, the predicate must throw a descriptive
|
||||
exception.
|
||||
*/
|
||||
drop(Table).
|
||||
|
||||
:- dynamic delete/1
|
||||
/*
|
||||
When this predicate is executed, the effect will be the deletion of all rows
|
||||
in the given table. The table itself should still exist after, but with no
|
||||
more rows.
|
||||
If the given table does not exist, the predicate must throw a descriptive
|
||||
exception.
|
||||
*/
|
||||
delete(Table).
|
||||
|
||||
:- dynamic delete/2
|
||||
/*
|
||||
When this predicate is executed, the effect will be the deletion of all rows
|
||||
from the given table that match all of the given conditions. The table
|
||||
must still exist after.
|
||||
If the given table does not exist, the predicate must throw a descriptive
|
||||
exception.
|
||||
A condition is any Prolog predicate that could have been typed at the
|
||||
prompt, but which may include selectors. Selectors are terms of the form
|
||||
+<column>where <column>should be replaced by a column name.
|
||||
(See tests.pl for some concrete usage examples.)
|
||||
*/
|
||||
delete(Table, Conds).
|
||||
|
||||
:- dynamic selec/4
|
||||
/*
|
||||
Note that the name of this predicate is selec (without t) for the simple
|
||||
reason that select/4 is already a built-in Prolog predicate.
|
||||
Table is the name of a single table.
|
||||
Selectors is either * or a list of selectors. These define the resulting
|
||||
projection. * means: select all column names from the table. Other
|
||||
selectors explicitly specify which columns to pick. (See above for what
|
||||
selectors look like.) For example, +name would select the column named
|
||||
name.
|
||||
Conds has the same form as in delete/2 and works the same way: only
|
||||
rows that match all conditions are selected.
|
||||
Finally, Projection unifies with <selectors>/<projection>, where:
|
||||
•<selectors>is the list of requested selectors.
|
||||
•<projection>is a list of values coming from a single row from the
|
||||
given table that matches the conditions. This mean this predicate
|
||||
should be able to backtrack to generate all projections that match
|
||||
the query.
|
||||
For example, selec(persons,[+id,+first],[],P) returns as first result
|
||||
P = [+id, +first]/[0, "Jeffrey"].
|
||||
To obtain all projections that match the query, one could use the Prolog
|
||||
query findall(X, selec(Table, Selectors, Conds, X), Projections).
|
||||
For example: findall(X, selec(persons,[+last],[],X), Projections)
|
||||
returns Projections = [[+last]/["Bowman"],[+last]/["Michaels"],. . . ]
|
||||
Or if you only want the rows (since the selectors are repeated):
|
||||
findall(X, selec(Table, Selectors, Conds, /X), Projections).
|
||||
For example:
|
||||
findall(Values, selec(persons,[+id,+first],[],Values), Projections)
|
||||
returns: Projections = [[0, "Jeffrey"], [1, "Lorena"], [2, "Joseph"], ...
|
||||
*/
|
||||
selec(Table, Selectors, Conds, Projection)
|
||||
|
||||
:- dynamic selec/3
|
||||
/*
|
||||
Simplified variant of the selec/4 predicate when there are no conditions
|
||||
to be checked.
|
||||
*/
|
||||
selec(TableOrTables, Selectors, Projection)
|
||||
|
||||
:- dynamic query/2
|
||||
/*
|
||||
where Query is a string whose syntax is defined by the following grammar:
|
||||
⟨query⟩ ::= ⟨select⟩ | ⟨insert ⟩
|
||||
⟨select⟩ ::= SELECT ⟨selectors⟩ FROM ⟨table⟩ [⟨where⟩];
|
||||
⟨selectors⟩ ::= * | ⟨cols⟩
|
||||
⟨cols⟩ ::= ⟨col ⟩ [, ⟨cols⟩]
|
||||
⟨where⟩ ::= WHERE ⟨cond ⟩
|
||||
⟨insert⟩ ::= INSERT INTO ⟨table⟩ [(⟨cols⟩)] VALUES (⟨values⟩);
|
||||
⟨values⟩ ::= ⟨value⟩ [, ⟨values⟩]
|
||||
About the notation: the pipe (|) and square brackets ([]) symbols in the
|
||||
production rules above denote choice and optionality, respectively.
|
||||
<table>and <col>denote table and column names (respectively). Ta-
|
||||
ble names are atoms, while column names should follow the format out-
|
||||
lined before (+<atom>). <cond>denotes a Prolog goal, in Prolog syntax
|
||||
— following the same format as the possible values of items of the Conds
|
||||
list passed to selec and delete.
|
||||
<value>denotes a prolog value that can be stored into a row. You do
|
||||
not need to handle parsing Prolog (<cond>and <value>) by yourself,
|
||||
we’ll show how to do it below.
|
||||
The semantics of this predicate is that of the SQL-predicate contained in
|
||||
the Query string.
|
||||
A “SELECT” query maps to the selec predicate, while an “INSERT”
|
||||
query maps to the insert predicate. For “SELECT”, all instances of
|
||||
<cond>(appearing in <where>) are mapped to the Conds parameter.
|
||||
<selectors>map to the Selectors parameter. Tables names (or *) are
|
||||
mapped to the Table parameter.
|
||||
For “INSERT”, if the <cols>part is absent, the mapping to insert/2
|
||||
is straightforward. If <cols>is present, you will have to:
|
||||
1. reorder the values according to the columns that are present;
|
||||
2. fill in the missing columns (if any) with a null default values.
|
||||
|
||||
Example:
|
||||
query("INSERT INTO cities (+name, +state)
|
||||
VALUES (\"Tempa\", \"Florida\");").
|
||||
maps to (for instance):
|
||||
insert(cities, ["Tempa", "Florida"]).
|
||||
When used with “SELECT”:
|
||||
•query/1 must display the results a bit like the rows predicate would.
|
||||
You have some flexibility here (displaying the selected column names
|
||||
is a nice touch for instance).
|
||||
•query/2 must pass the Result parameter as last parameter to the
|
||||
selec/4 predicate.
|
||||
For “INSERT”, nothing needs to be printed by query/1 or in case of
|
||||
success, and if query/2 is used the Result parameter can be ignored.
|
||||
*/
|
||||
query(Query, Result)
|
||||
|
||||
:- dynamic query/1
|
||||
/*
|
||||
cf. query/2
|
||||
*/
|
||||
query(Query)
|
Loading…
Reference in New Issue