A query is the launching point for eXPL execution and defines a goal to be achieved. The query along with the rest of the eXPL program is compiled and executed in the context of a Java application which must have access to the eXPL parser library and any resources on which the program depends. It is possible to report the query solution using a library, eg. output results on the system console, but normally the results will be extracted from either a result object returned from executing the query or a handler called at the end of every successful unification/evaluation cycle.
The next example contains an eXPL query name "customer_charge" which references 2 axiom sources, "charge" and "customer" and 2 templates, "freight" and "customer_freight":
{"Athens", 23 ),
{"Sparta", 13 ),
{"Milos", 17);
axiom customer()
{"Marathon Marble", "Sparta"}
{"Acropolis Construction", "Athens"}
{"Agora Imports", "Sparta"}
{"Spiros Theodolites", "Milos"};
template freight(city, charge);
template customer_freight(
name,
city ? city == freight.city,
charge
);
query customer_charge(charge:freight, customer:customer_freight);
This query can be run in the GreekConstruction application of the tutorial2. The console output when the query is run is:
customer_freight(name = Acropolis Cons., city = Athens, charge = 23)
freight(city = Sparta, charge = 13)
customer_freight(name = Marathon Marble, city = Sparta, charge = 13)
freight(city = Sparta, charge = 13)
customer_freight(name = Agora Imports, city = Sparta, charge = 13)
freight(city = Milos, charge = 17)
customer_freight(name = Spiros Theod., city = Milos, charge = 17)
The "customer_charge" query is declared thus:
It has 2 parameters, each specifying an axiom:template pair. The query proceeds in stages. At each stage the query unifies an axiom with a template. If a match occurs, the template is evaluated and the query proceeds to the next stage, otherwise, the cycle starts at the next iteration. The result of a successful unify/evaluate step is an axiom, named the same as the template, containing the results of the evaluation. This axiom is passed on to the next stage where it can be referenced using a 2-part name eg. "freight.city".
In stage 1, axiom "charge" is paired to template "freight" and in stage 2, axiom "customer" is paired to template "customer_freight". The query tries to combine all charge axioms with all customer axioms, but the solution contains only those cases where the name of the charge city corresponds to the customer city.
Cascading Queries
The customer_charge query is an example of a cascading query which exhaustively tries every combination of charge axioms paired with customer axioms. In relational database terms, it performs join of the "charge" table to the "customer" table. The analogy holds also in the fact the query result can be in the form of a new axiom collection (a new database table) or simply read axiom by axiom (row by row) into a process to publish the results. With eXPL there is the flexibility in arranging how information is delivered to the query and how the solution is shaped. In the first Greek Construction example, we see unnamed terms input into the query turn to named terms in the solution. The order of terms is also determined by template order.
Optimisation
An obvious flaw in using unification to find query solutions is that it uses the expensive approach to sifting through data to extract information. A query may involve reading every record in from an axiom source multiple times. If performance becomes unacceptable because of this issue, then some form of optimization is required and is best implemented at the source of the data for best efficiency. For example, when sourcing from a database, a prepared statement can be used to exclude irrelevant records. This can be considered a division of labour where the data source takes care of the bulky work leaving the eXPL script to apply high level logic, formulation and presentation. An alternate approach is to have eXPL queries do an initial pass after hours to produce smaller data sets containing just the required raw data. This is akin to running batch jobs to build database indexes. The point is that optimization, if required, will take time, skill and ingenuity, but is applicable to eXPL.
Logic Chain
A logic chain is appended to a query to contribute more information based on solution found so far. Query chaining is applied at the stage when a solution has been found and only more details are required. Here is an example where two logic chain queries add payment and freight charges to customer account details:
{"Marathon Marble", "Sparta"}
{"Acropolis Construction", "Athens"}
{"Agora Imports", "Sparta"}
{"Spiros Theodolites", "Milos"};
axiom fee (name, fee)
{"Marathon Marble", 61}
{"Acropolis Construction", 47}
{"Agora Imports", 49}
{"Spiros Theodolites", 57};
axiom freight (city, freight)
{"Athens", 5 }
{"Sparta", 16 }
{"Milos", 22};
template customer(name, city);
template account(name ? customer.name == name, fee);
template delivery(city ? customer.city == city, freight);
query greek_business(customer:customer)
-> (fee:account) -> (freight:delivery);
