\documentclass[a4paper,12pt]{report}
\usepackage{url}
\usepackage{enumitem}
\usepackage{palatino}
\usepackage[cmex10]{amsmath}
\usepackage{stmaryrd,amssymb}
\usepackage{graphicx}
\usepackage{amsfonts}
\usepackage{rotating}
\usepackage{listings}
\usepackage{xcolor}
\usepackage{url,boxedminipage,listings}
\usepackage{booktabs}
\usepackage{rotating}
\usepackage{array}
\usepackage{color,url,varioref,xcolor}
\usepackage{alltt,epsfig,comment}
\usepackage{supertabular,fancyhdr}
\usepackage{multirow}
\usepackage{url}
\usepackage{xspace}
\usepackage{dsfont}
\usepackage[english]{babel}
\usepackage{todonotes}

\usepackage{pdfpages}
\usepackage[font={footnotesize,sl}, labelfont=bf] {caption}

\usepackage{tikz}
\usetikzlibrary{arrows}
\usetikzlibrary{automata}
\usetikzlibrary{positioning}
\usetikzlibrary{er}

% HAS TO BE LAST PACKAGE:
\usepackage[pdftex,bookmarks=true,pageanchor=false]{hyperref}

%Nice tilde operator
\lstset{
    literate={~} {$\sim\ $}{1}
}

% Eiffel Code Stuff
\lstset{language=OOSC2Eiffel,basicstyle=\ttfamily\small}
\definecolor{codebg}{rgb}{0.95,0.95,0.95}
\setlength{\headheight}{28pt}

% Inline Eiffel Code
\let\e\lstinline
% Eiffel Identifiers or expressions
\newcommand{\eid}[1]{\textsl{{\color[HTML]{000000} #1}}}
% Eiffel Class names
%\newcommand{\ecl}[1]{\textsl{{\color[HTML]{3333FF} #1}}}
\newcommand{\ecl}[1]{\textsl{{\color[HTML]{000000} #1}}}
% Eiffel Keywords
%\newcommand{\ekey}[1]{\textbf{{\color[HTML]{333399} #1}}}
\newcommand{\ekey}[1]{\textbf{{\color[HTML]{000000} #1}}}

\newcommand{\distance}[2]{\ensuremath{#1\leftrightarrow#2}}

\lstset{escapechar=\$}

\newcommand{\blankpage}{
\newpage
\thispagestyle{empty}
\mbox{}
\newpage
}


\title {The ABEL Persistence Library Tutorial}
\author {
	Roman Schmocker, Pascal Roos, Marco Piccioni\\\\
	Last updated:
}


\begin{document}

\maketitle

\tableofcontents

\pagenumbering{arabic}

\chapter{Introducing ABEL}
ABEL (A Better EiffelStore Library) is an object-oriented persistence library written in Eiffel and aiming at seamlessly integrating various kinds of data stores.
 
\section{Setting things up}
ABEL is shipped with EiffelStudio in the \emph{unstable} directory.
You can get the latest code from the SVN directory \footnote{\url{https://svn.eiffel.com/eiffelstudio/trunk/Src/unstable/library/persistency/abel}}.

\section{Getting started}
We will be using \lstinline!PERSON! objects to show the usage of the API. 
In the source code below you will see that ABEL handles objects "as they are", meaning that to make them persistent you don't need to add any dependencies to their class source code.

\begin{lstlisting}[language=OOSC2Eiffel, captionpos=b, caption={The PERSON class}, label={lst:person_class}]
class PERSON

create
	make

feature {NONE} -- Initialization

	make (first, last: STRING)
			-- Create a newborn person.
		require
			first_exists: not first.is_empty
			last_exists: not last.is_empty
		do
			first_name := first
			last_name := last
			age:= 0
		ensure
			first_name_set: first_name = first
			last_name_set: last_name = last
			default_age: age = 0
		end

feature -- Basic operations

	celebrate_birthday
			-- Increase age by 1.
		do
			age:= age + 1
		ensure
			age_incremented_by_one: age = old age + 1
		end

feature -- Access

	first_name: STRING
		-- The person's first name.

	last_name: STRING
		-- The person's last name.

	age: INTEGER
		-- The person's age.

invariant
	age_non_negative: age >= 0
	first_name_exists: not first_name.is_empty
	last_name_exists: not last_name.is_empty
end

\end{lstlisting}

There are three very important classes in ABEL:
\begin{itemize}
 \item The deferred class \lstinline!PS_REPOSITORY! provides an abstraction to the actual storage mechanism. It can only be used for read operations.
 \item The \lstinline!PS_TRANSACTION! class represents a transaction and can be used to execute read, insert and update operations. Any \lstinline!PS_TRANSACTION! object is bound to a \lstinline!PS_REPOSITORY!.

 \item The \lstinline!PS_QUERY [G]! class is used to describe a read operation for objects of type \lstinline!G!.

 
\end{itemize}
To start using the library, we first need to create a \lstinline!PS_REPOSITORY!.
For this tutorial we are going to use an in-memory repository to avoid setting up any external database.
Each ABEL backend will ship a repository factory class to make initialization easier.
The factory for the in-memory repository is called \lstinline!PS_IN_MEMORY_REPOSITORY_FACTORY!.

\begin{lstlisting}[language=OOSC2Eiffel, captionpos=b, caption={The START class}, label={lst:tutorial_class}]
class START

create
  make

feature {NONE} -- Initialization

	make
			-- Initialization for `Current'.
		local
			factory: PS_IN_MEMORY_REPOSITORY_FACTORY
		do
			create factory.make
			repository := factory.new_repository
			
			create criterion_factory
			explore
		end

	repository: PS_REPOSITORY
		-- The main repository.

	end

end
\end{lstlisting}
We will use \lstinline!criterion_factory! later in this tutorial.
The feature \lstinline!explore! will guide us through the rest of this API tutorial and show the possibilities in ABEL.

\chapter{Basic operations}

\section{Inserting}

You can insert a new object using feature \lstinline{insert} in \lstinline{PS_TRANSACTION}.
As every write operation in ABEL needs to be embedded in a transaction, you first need to create a \lstinline{PS_TRANSACTION} object.
Let's add three new persons to the database:
\begin{lstlisting}[language=OOSC2Eiffel, captionpos=b, caption={Insertion code.}, label={lst:tutorial_insert}]
	insert_persons
			-- Populate the repository with some person objects.
		local
			p1, p2, p3: PERSON
			transaction: PS_TRANSACTION
		do
				-- Create persons
			create p1.make (...)
			create ...

				-- We first need a new transaction.
			transaction := repository.new_transaction

				-- Now we can insert all three persons.
			if not transaction.has_error then
				transaction.insert (p1)
			end
			if not transaction.has_error then
				transaction.insert (p2)
			end
			if not transaction.has_error then
				transaction.insert (p3)
			end

				-- Commit the changes.
			if not transaction.has_error then
				transaction.commit
			end

				-- Check for errors.
			if transaction.has_error then
				print ("An error occurred!%N")
			end
		end
\end{lstlisting}

\section{Querying}
\label{section:querying}
A query for objects is done by creating a \lstinline!PS_QUERY [G]! object and executing it using features of \lstinline!PS_REPOSITORY! or \lstinline!PS_TRANSACTION!.
The generic parameter \lstinline!G! denotes the type of objects that should be queried.

After a successful execution of the query, you can iterate over the result using the \lstinline!across! syntax. 
The feature \lstinline{print_persons} below shows how to get and print a list of persons from the repository:

\begin{lstlisting}[language=OOSC2Eiffel, captionpos=b, caption={Print all PERSON objects.}, label={lst:simple_query}]
	print_persons
			-- Print all persons in the repository
		local
			query: PS_QUERY[PERSON]
		do
				-- First create a query for PERSON objects.
			create query.make

				-- Execute it against the repository.
			repository.execute_query (query)

				-- Iterate over the result.
			across
				query as person_cursor
			loop
				print (person_cursor.item)
			end
			
				-- Check for errors. 
			if query.has_error then
				print ("An error occurred!%N")
			end

				-- Don't forget to close the query.
			query.close
		end
\end{lstlisting}

In a real database the result of a query may be very big, and you are probably only interested in objects that meet certain criteria, e.g. all persons of age 20. 
You can read more about it in Chapter ~\ref{sec:advanced_queries}.

Please note that ABEL does not enforce any kind of order on a query result.

\section{Updating}

Updating an object is done through feature \lstinline{update} in \lstinline{PS_TRANSACTION}.
Like the insert operation, an update needs to happen within a transaction.
Note that in order to \lstinline!update! an object, we first have to retrieve it.

Let's update the \lstinline{age} attribute of Berno Citrini by celebrating his birthday:

\begin{lstlisting}[language=OOSC2Eiffel, captionpos=b, caption={Update Berno Citrini's age.}, label={lst:tutorial_update}]
	update_berno_citrini
			-- Increase the age of Berno Citrini by one.
		local
			query: PS_QUERY[PERSON]
			transaction: PS_TRANSACTION
			berno: PERSON
		do
			print ("Updating Berno Citrini's age by one.%N")

				-- Create query and transaction.
			create query.make
			transaction := repository.new_transaction

				-- As we're doing a read followed by a write, we
				-- need to execute the query within a transaction.
			if not transaction.has_error then
				transaction.execute_query (query)
			end

				-- Search for Berno Citrini
			across
				query as cursor
			loop
				if cursor.item.first_name ~  "Berno" then
					berno := cursor.item

						-- Change the object.
					berno.celebrate_birthday

						-- Perform the database update.
					transaction.update (berno)
				end
			end

				-- Cleanup
			query.close
			if not transaction.has_error then
				transaction.commit
			end
			
			if transaction.has_error then
				print ("An error occurred.%N")
			end
		end

\end{lstlisting}

To perform an update the object first needs to be retrieved or inserted within the same transaction.
Otherwise ABEL cannot map the Eiffel object to its database counterpart (see also Section~\ref{section:dealing_with_known_objects}).

\section{Deleting}
\label{section:simple_delete}

ABEL does not support explicit deletes any longer, as it is considered dangerous for shared objects.
Instead of deletion it is planned to introduce a garbage collection mechanism in the future.

\section{Dealing with Known Objects}
\label{section:dealing_with_known_objects}

Within a transaction ABEL keeps track of objects that have been inserted or queried.
This is important because in case of an update, the library internally needs to map the object in the current execution of the program to its specific entry in the database.

Because of that, you can't update an object that is not yet known to ABEL.
As an example, the following functions will fail:

\begin{lstlisting}[language=OOSC2Eiffel, captionpos=b, caption={Common pitfalls with update.}, label={lst:failing_update_delete}]
	failing_update
			-- Trying to update a new person object.
		local
			bob: PERSON
			transaction: PS_TRANSACTION
		do
			create bob.make ("Robert", "Baratheon")
			transaction := repository.new_transaction
				-- Error: Bob was not inserted / retrieved before.
				-- The result is a precondition violation.
			transaction.update (bob)
			transaction.commit
		end

	update_after_commit
			-- Update after transaction committed.
		local
			joff: PERSON
			transaction: PS_TRANSACTION
		do
			create joff.make ("Joffrey", "Baratheon")
			transaction := repository.new_transaction
			transaction.insert (joff)
			transaction.commit

			joff.celebrate_birthday

				-- Prepare can be used to restart a transaction.
			transaction.prepare

				-- Error: Joff was not inserted / retrieved before.
				-- The result is a precondition violation.
			transaction.update (joff)
			
				-- Note: After commit and prepare,`transaction'
				-- represents a completely new transaction.
		end
\end{lstlisting}

The feature \lstinline{is_persistent} in \lstinline!PS_TRANSACTION! can tell you if a specific object is known to ABEL and hence has a link to its entry in the database.

\chapter{Advanced Queries}
\label{sec:advanced_queries}

\section{The query mechanism}

As you already know from Section~\ref{section:querying}, queries to a database are done by creating a \lstinline!PS_QUERY[G]! object 
and executing it against a \lstinline!PS_TRANSACTION! or \lstinline!PS_REPOSITORY!.
The actual value of the generic parameter \lstinline!G! determines the type of the objects that will be returned.
By default objects of a subtype of \lstinline!G! will also be included in the result set.

ABEL will by default load an object completely, meaning all objects that can be reached by following references will be loaded as well (see also Chapter ~\ref{chapter:references}).

\section{Criteria}

You can filter your query results by setting criteria in the query object, using feature \lstinline{set_criterion} in \lstinline{PS_QUERY}.
There are two types of criteria: predefined and agent criteria.

\subsection{Predefined Criteria}
When using a predefined criterion you pick an attribute name, an operator and a value. 
During a read operation, ABEL checks the attribute value of the freshly retrieved object against the value set in the criterion, and filters away objects that don't satisfy the criterion.

Most of the supported operators are pretty self-describing (see class \lstinline{PS_CRITERION_FACTORY} in Section~\ref{sec:creating_criteria_objects}).
An exception could be the \lstinline!like! operator, which does pattern-matching on strings.
You can provide the \lstinline!like! operator with a pattern as a value. The pattern can contain the wildcard characters \lstinline!*! and \lstinline!?!.
The asterisk stands for any number (including zero) of undefined characters, and the question mark means exactly one undefined character.

You can only use attributes that are strings or numbers, but not every type of attribute supports every other operator. Valid combinations for each type are:

 \begin{itemize}
  \item Strings: =, like
  \item Any numeric value: $=, <, <=, >, >=$
  \item Booleans: =
 \end{itemize}

Note that for performance reasons it is usually better to use predefined criteria, because they can be compiled to SQL and hence the result can be filtered in the database.

\subsection{Agent Criteria}

An agent criterion will filter the objects according to the result of an agent applied to them.

The criterion is initialized with an agent of type \lstinline!PREDICATE [ANY, TUPLE [ANY]]!. 
There should be either an open target or a single open argument, and the type of the objects in the query result should conform to the agent's open operand. 
For an example see Section~\ref{sec:creating_criteria_objects}.

\subsection{Creating criteria objects}
\label{sec:creating_criteria_objects}
The criteria instances are best created using the \lstinline!PS_CRITERION_FACTORY! class.

The main features of the class are the following: 

\begin{lstlisting}[language=OOSC2Eiffel, captionpos=b, caption={The CRITERION\_FACTORY class interface}, label={lst:factory_interface}]
class
	PS_CRITERION_FACTORY
create
	default_create

feature -- Creating a criterion

	new_criterion alias "()" (tuple: TUPLE [ANY]): PS_CRITERION
		-- Creates a new criterion according to a `tuple'
		-- containing either a single PREDICATE or three 
		-- values of type [STRING, STRING, ANY].

	new_agent (a_predicate: PREDICATE [ANY, TUPLE [ANY]]): PS_CRITERION
		-- Creates an agent criterion.

	new_predefined (object_attribute: STRING; 
		operator: STRING; value: ANY): PS_CRITERION
		-- Creates a predefined criterion.

feature -- Operators

	equals: STRING = "="

	greater: STRING = ">"

	greater_equal: STRING = ">="

	less: STRING = "<"

	less_equal: STRING = "<="

	like_string: STRING = "like"

end
\end{lstlisting}

Assuming you have an object \lstinline{f: PS_CRITERION_FACTORY}, to create a new criterion you have two possibilities:

 \begin{itemize}
  \item The "traditional" way
  \begin{itemize}
  \item \lstinline!f.new_agent (agent an_agent)!
  \item \lstinline!f.new_predefined (an_attr_name, an_operator, a_val)!
  \end{itemize}
  \item The "syntactic sugar" way
  \begin{itemize}
  \item \lstinline!f (an_attr_name, an_operator, a_value)!
  \item \lstinline!f (agent an_agent)!
  \end{itemize} 
  \end{itemize}
  
\begin{lstlisting}[language=OOSC2Eiffel, captionpos=b, caption={Different ways of creating criteria.}, label={lst:factory_usage}]

	create_criteria_traditional : PS_CRITERION
		-- Create a new criteria using the traditional approach.
		do
			-- for predefined criteria
			Result:= 
				factory.new_predefined ("age", factory.less, 5)

			-- for agent criteria
			Result := 
				factory.new_agent (agent age_more_than (?, 5))
		end

	create_criteria_parenthesis : PS_CRITERION
		-- Create a new criteria using parenthesis alias.
		do
			-- for predefined criteria
			Result:= factory ("age", factory.less, 5)

			-- for agent criteria
			Result := factory (agent age_more_than (?, 5))
		end			

	age_more_than (person: PERSON; age: INTEGER): BOOLEAN
		-- An example agent
		do
			Result:= person.age > age
		end

\end{lstlisting}

\subsection{Combining criteria}

You can combine multiple criterion objects by using the standard Eiffel logical operators. 
For example, if you want to search for a person called ``Albo Bitossi'' with $age <= 20$, you can just create a criterion object for each of the constraints and combine them:  

\begin{lstlisting}[language=OOSC2Eiffel, captionpos=b, caption={Combining criteria.}, label={lst:search_albo_bitossi}]

	composite_search_criterion : PS_CRITERION
		-- Combining criterion objects.
		local
			first_name_criterion: PS_CRITERION
			last_name_criterion: PS_CRITERION
			age_criterion: PS_CRITERION
		do
			first_name_criterion:= 
				factory ("first_name", factory.equals, "Albo")

			last_name_criterion := 
				factory ("last_name", factory.equals, "Bitossi")

			age_criterion := 
				factory (agent age_more_than (?, 20))
			
			Result := first_name_criterion and last_name_criterion and not age_criterion

			-- Shorter version: 
			Result := factory ("first_name", "=", "Albo") 
				and factory ("last_name", "=", "Bitossi") 
				and not factory (agent age_more_than (?, 20))
		end
\end{lstlisting}

ABEL supports the three standard logical operators \lstinline!AND!, \lstinline!OR! and \lstinline!NOT!. 
The precedence rules are the same as in Eiffel, which means that \lstinline!NOT! is stronger than \lstinline!AND!, which in turn is stronger than \lstinline!OR!.

\chapter{Dealing with references}
\label {chapter:references}

In ABEL, a basic type is an object of type \lstinline!STRING!, \lstinline!BOOLEAN!, \lstinline!CHARACTER! or any numeric class like \lstinline!REAL! or \lstinline!INTEGER!.
The \lstinline!PERSON! class only has attributes of a basic type. 
However, an object can contain references to other objects. ABEL is able to handle these references by storing and reconstructing the whole object graph 
(an object graph is roughly defined as all the objects that can be reached by recursively following all references, starting at some root object).

\section{Inserting objects with dependencies}
Let's look at the new class \lstinline!CHILD!:

\begin{lstlisting}[language=OOSC2Eiffel, captionpos=b, caption={The CHILD class.}, label={lst:child_class}]

class
	CHILD

create
	make

feature {NONE} -- Initialization

	make (first, last: STRING)
			-- Create a new child.
		require
			first_exists: not first.is_empty
			last_exists: not last.is_empty
		do
			first_name := first
			last_name := last
			age := 0
		ensure
			first_name_set: first_name = first
			last_name_set: last_name = last
			default_age: age = 0
		end

feature -- Access

	first_name: STRING
			-- The child's first name.

	last_name: STRING
			-- The child's last name.

	age: INTEGER
			-- The child's age.

	father: detachable CHILD
			-- The child's father.

feature -- Element Change

	celebrate_birthday
			-- Increase age by 1.
		do
			age := age + 1
		ensure
			age_incremented_by_one: age = old age + 1
		end

	set_father (a_father: CHILD)
			-- Set a father for the child.
		do
			father := a_father
		ensure
			father_set: father = a_father
		end

invariant
	age_non_negative: age >= 0
	first_name_exists: not first_name.is_empty
	last_name_exists: not last_name.is_empty
end


\end{lstlisting}


This adds in some complexity: 
Instead of having a single object, ABEL has to insert a \lstinline!CHILD!'s mother and father as well, and it has to repeat this procedure if their parent attribute is also attached. 
The good news are that the examples above will work exactly the same.

However, there are some additional caveats to take into consideration. 
Let's consider a simple example with \lstinline!CHILD! objects ``Baby Doe'', ``John Doe'' and ``Grandpa Doe''.
From the name of the object instances you can already guess what the object graph looks like: 

	\begin{center}
\begin{tikzpicture}[->,>=stealth',shorten >=1pt,auto,node distance=5cm,
  thick,main node/.style={rectangle,fill=white,draw}]

  \node[main node] (1) {$Baby Doe$};
  \node[main node] (2) [right of=1] {$John Doe$};
  \node[main node] (3) [right of=2] {$Grandpa Doe$};

  \path
    (1) edge node {$father$} (2)
    (2) edge node {$father$} (3);
\end{tikzpicture}
	\end{center}

Now if you insert ``Baby Doe'', ABEL will by default follow all references and insert every single object along the object graph, which means that ``John Doe'' and ``Grandpa Doe'' will be inserted as well.
This is usually the desired behavior, as objects are stored completely that way, but it also has some side effects we need to be aware of:

\begin{itemize}
\item Assume an insert of ``Baby Doe'' has happened to an empty database. 
If you now query the database for \lstinline!CHILD! objects, it will return exactly the same object graph as above, 
but the query result will actually have three items, as the object graph consists of three single \lstinline!CHILD! objects.
	
\item The insert of ``John Doe'' and ``Grandpa Doe'', after inserting ``Baby Doe'', is internally changed to an update operation because both objects are already in the database.
This might result in some undesired overhead which can be avoided if you know the object structure.
\end{itemize}

In our main tutorial class \lstinline{START} we have the following two features that show how to deal with object graphs. 
You will notice it is very similar to the corresponding routines for the flat \lstinline!PERSON! objects.

\begin{lstlisting}[language=OOSC2Eiffel, captionpos=b, caption={Dealing with object graphs.}, label={lst:references_handling}]
	insert_children
			-- Populate the repository with some children objects.
		local
			c1, c2, c3: CHILD
			transaction: PS_TRANSACTION
		do
				-- Create the object graph.
			create c1.make ("Baby", "Doe")
			create c2.make ("John", "Doe")
			create c3.make ("Grandpa", "Doe")
			c1.set_father (c2)
			c2.set_father (c3)

			print ("Insert 3 children in the database.%N")
			transaction := repository.new_transaction

				-- It is sufficient to just insert "Baby Joe", 
				-- as the other CHILD objects are (transitively) 
				-- referenced and thus inserted automatically.
			if not transaction.has_error then
				transaction.insert (c1)
			end

			if not transaction.has_error then
				transaction.commit
			end

			if transaction.has_error then
				print ("An error occurred during insert!%N")
			end
		end

	print_children
			-- Print all children in the repository
		local
			query: PS_QUERY[CHILD]
		do
			create query.make
			repository.execute_query (query)
			
				-- The result will also contain
				-- all referenced CHILD objects.
			across
				query as person_cursor
			loop
				print (person_cursor.item)
			end

			query.close
		end
\end{lstlisting}
 
\section{Going deeper in the Object Graph}
\label{sec:going_deeper_in_object_graph}
ABEL has no limits regarding the depth of an object graph, and it will detect and handle reference cycles correctly. 
You are welcome to test ABEL's capability with very complex objects, however please keep in mind that this may impact performance significantly.

% To overcome this problem, you can either use simple object structures, or you can tell ABEL to only load or store an object up to a certain depth.
% The default ABEL's behavior with respect to the object graph can be changed by using feature \lstinline{default_object_graph} in class \lstinline{PS_REPOSITORY} and passing an appropriate object of type \lstinline{PS_DEFAULT_OBJECT_GRAPH_SETTINGS}.

%\chapter{Advanced Initialization}
%\label{chapter:advanced_initialization}
%
%The in-memory repository we've used so far doesn't store data permanently.
%This is acceptable for testing or for a tutorial, but not in a real application.
%Therefore, we will be now looking at the ABEL support for the MySQL and SQLite databases. For MySQL, you will need to create a \lstinline!PS_MYSQL_DATABASE! object and a \lstinline!PS_MYSQL_STRINGS! object.
%Then you will use them to create a \lstinline!PS_GENERIC_LAYOUT_SQL_BACKEND!, which you will need in turn to create the \lstinline!PS_RELATIONAL_REPOSITORY!.
%
%The following little factory class shows the process for both a MySQL and a SQLite database:
%
%\begin{lstlisting}[language=OOSC2Eiffel, captionpos=b, caption={Setting up a MySQL and a SQLite repositories}, label={lst:advanced_initialization}]
%
%class 
%	REPOSITORY_FACTORY
%
%feature -- Connection details
%	
%	username:STRING = "tutorial"
%	password:STRING = "tutorial"
%
%	db_name:STRING = "tutorial"
%	db_host:STRING = "127.0.0.1"
%	db_port:INTEGER = 3306
%
%	sqlite_filename: STRING = "tutorial.db"
%
%feature -- Factory methods
%
%	create_mysql_repository: PS_RELATIONAL_REPOSITORY
%		-- Create a MySQL repository
%		local
%			database: PS_MYSQL_DATABASE
%			mysql_strings: PS_MYSQL_STRINGS
%			backend: PS_GENERIC_LAYOUT_SQL_BACKEND
%		do
%			create database.make (username, password, db_name, db_host, db_port)
%			create mysql_strings
%			create backend.make (database, mysql_strings)
%			create Result.make (backend)
%		end
%
%	create_sqlite_repository: PS_RELATIONAL_REPOSITORY
%		-- Create an SQLite repository
%		local
%			database: PS_SQLITE_DATABASE
%			sqlite_strings: PS_SQLITE_STRINGS
%			backend: PS_GENERIC_LAYOUT_SQL_BACKEND
%		do
%			create database.make (sqlite_filename)
%			create sqlite_strings
%			create backend.make (database, sqlite_strings)
%			create Result.make (backend)
%		end
%end
%
%\end{lstlisting}
%
%All examples from this tutorial work exactly the same, regardless of the specific kind of repository you are working with.

\chapter{Tuple queries}

Consider a scenario in which you just want to have a list of all first names of \lstinline !CHILD! objects in the database. 
Loading every attribute of each object of type \lstinline!CHILD! might lead to a very bad performance, especially if there is a big object graph attached to each \lstinline!CHILD! object.

To solve this problem ABEL allows queries which return data in \lstinline!TUPLE! objects.
Tuple queries are executed by calling  \lstinline!execute_tuple_query (a_tuple_query)! in either \lstinline!PS_REPOSITORY! or \lstinline!PS_TRANSACTION!, 
where \lstinline!a_tuple_query! is of type \lstinline!PS_TUPLE_QUERY [G]!.
The result is an iteration cursor over a list of tuples in which the attributes of an object are stored.

\section{Tuple queries and projections}
The \lstinline!projection! feature in a \lstinline!PS_TUPLE_QUERY! defines which attributes shall be included in the result \lstinline!TUPLE!. 
Additionally, the order of the attributes in the projection array is the same as the order of the elements in the result tuples.

By default, a \lstinline!PS_TUPLE_QUERY! object will only return values of attributes which are of a basic type, so no references are followed during a retrieve.
You can change this default by calling \lstinline{set_projection}.
If you include an attribute name whose type is not a basic one, ABEL will actually retrieve and build the attribute object, and not just another tuple.

\section{Tuple queries and criteria}
You are restricted to use predefined criteria in tuple queries, because agent criteria expect an object and not a tuple. 
You can still combine them with logical operators, and even include a predefined criterion on an attribute that is not present in the projection list.
These attributes will be loaded internally to check if the object satisfies the criterion, and then they are discarded for the actual result.

\section {Example}

\begin{lstlisting}[language=OOSC2Eiffel, captionpos=b, caption={Using tuple queries.}, label={lst:tuple_query_simple}]

	explore_tuple_queries
			-- See what can be done with tuple queries.
		local
			query: PS_TUPLE_QUERY [CHILD]
			transaction: PS_TRANSACTION
			projection: ARRAYED_LIST [STRING]
		do
				-- Tuple queries are very similar to normal queries.
				-- I.e. you can query for CHILD objects by creating
				-- a PS_TUPLE_QUERY [CHILD]
			create query.make

				-- It is also possible to add criteria. Agent criteria 
				-- are not supportedfor tuple queries however.
				-- Lets search for CHILD objects with last name Doe.
			query.set_criterion (criterion_factory
				("last_name", criterion_factory.equals, "Doe"))

				-- The big advantage of tuple queries is that you can 
				-- define which attributes should be loaded. 
				-- Thus you can avoid loading a whole object graph
				-- if you're just interested in e.g. the first name.
			create projection.make_from_array (<<"first_name">>)
			query.set_projection (projection)

				-- Execute the tuple query.
			repository.execute_tuple_query (query)

				-- The result of the query is a TUPLE containing the 
				-- requested attribute.

			print ("Print all first names using a tuple query:%N")
			
			across
				query as cursor
			loop
					-- It is possible to downcast the TUPLE 
					-- to a tagged tuple with correct type.
				check 
					attached {TUPLE [first_name: STRING]} 
						cursor.item as tuple 
				then
					print (tuple.first_name + "%N")
				end
			end
			
			  -- Cleanup and error handling.
			query.close
			if query.has_error then
				print ("An error occurred!%N")
			end			
		end
\end{lstlisting}

\chapter{Error handling}

As ABEL is dealing with I/O and databases, a runtime error may happen at any time.
ABEL will inform you of an error by setting the \lstinline!has_error! attribute to True in \lstinline!PS_QUERY! or \lstinline!PS_TUPLE_QUERY! and, if available, in \lstinline!PS_TRANSACTION!.
The attribute should always be checked in the following cases:
\begin{itemize}
 \item Before invoking a library command.
 \item After a transaction commit.
 \item After iterating over the result of a read-only query.
\end{itemize}

ABEL maps database specific error messages to its own representation for errors, which is a hierarchy of classes rooted at \lstinline!PS_ERROR!.
In case of an error, you can find an ABEL error description in the \lstinline!error! attribute in all classes suppoorting the \lstinline!has_error! attribute.
The following list shows all error classes that are currently defined with some examples (the \lstinline!PS_! prefix is omitted for brevity):

\begin{itemize}
\item \lstinline!CONNECTION_SETUP_ERROR!: No internet link, or a deleted serialization file.
\item \lstinline!AUTHORIZATION_ERROR!: Usually a wrong password.
\item \lstinline!BACKEND_ERROR!: An unrecoverable error in the storage backend, e.g. a disk failure.
\item \lstinline!INTERNAL_ERROR!: Any error happening inside ABEL.
\item \lstinline!PS_OPERATION_ERROR!: For invalid operations, e.g. no access rights to a table.
\item \lstinline!TRANSACTION_ABORTED_ERROR!: A conflict between two transactions.
\item \lstinline!MESSAGE_NOT_UNDERSTOOD_ERROR!: Malformed SQL or JSON statements.
\item \lstinline!INTEGRITY_CONSTRAINT_VIOLATION_ERROR!: The operation violates an integrity constraint in the database.
\item \lstinline!EXTERNAL_ROUTINE_ERROR!: An SQL routine or triggered action has failed.
\item \lstinline!VERSION_MISMATCH!: The stored version of an object isn't compatible any more to the current type.
\end{itemize}

For your convenience, there is a visitor pattern for all ABEL error types. 
You can just implement the appropriate functions and use it for your error handling code.

\begin{lstlisting}[language=OOSC2Eiffel, captionpos=b, caption={Sample error handling using a visitor.}, label={lst:error_visitor_example}]

class
	MY_PRIVATE_VISITOR

inherit
	PS_DEFAULT_ERROR_VISITOR
		redefine
			visit_transaction_aborted_error,
			visit_connection_setup_error
		end

feature -- Visitor features

	visit_transaction_aborted_error (transaction_aborted_error: PS_TRANSACTION_ABORTED_ERROR)
		-- Visit a transaction aborted error
		do
			print ("Transaction aborted")
		end

	visit_connection_setup_error (connection_setup_error: PS_CONNECTION_SETUP_ERROR)
		-- Visit a connection setup error
		do
			print ("Wrong login")
		end

end

\end{lstlisting}


% \chapter{CouchDB Support}
% 
% ABEL does not only work with an in-memory database. It is also able to store objects in other database, both relational (like MySQL and SQLite) and non-relational like CouchDB, always using the same API.
% 
% \section{What is CouchDB}
% 
% CouchDB is a free, open-source document-oriented database \footnote{\url{http://couchdb.apache.org}}. CouchDB stores objects on a persistent database using JSON documents.
% JSON is a textual notation similar to XML that stores Eiffel objects like this:
% \begin{lstlisting}[language=OOSC2Eiffel, captionpos=b, caption={Sample Eiffel Object in JSON}, label={lst:person_json}]
% {
% 	"firstname": "Albo",
% 	"lastname": "Bitossi",
% 	"age": 0
% }
% \end{lstlisting}
% 
% \section{Setting up CouchDB}
% 
% Before we can start using CouchDB from within Eiffel we have to set it up either on a local machine or get hold of a database on the internet. To install CouchDB locally visit \url{www.couchdb.com} and download the appropriate package.
% 
% Once installed, CouchDB should be running in the background and is accessible trough a browser by accessing \emph{127.0.0.1:5984/\_utils}
% To work with CouchDB in Eiffel we have created another tutorial which you can get at \emph{abel/apps/sample/tutorial-couchdb/}. Look for the \emph{tutorial\_project.ecf} and open it with EiffelStudio.
% 
% \section{Getting started with CouchDB}
% 
% On the surface there is not much difference between using the in-memory database and CouchDB. You may notice that all we changed in the tutorial is the call to the repo\_factory. 
% \begin{lstlisting}[language=OOSC2Eiffel, captionpos=b, caption={The CouchDB Tutorial}, label={lst:explore_couchdb}]
% 	explore
% 			-- Tutorial code.
% 		local
% 			p1, p2, p3: PERSON
% 			c1, c2, c3: CHILD
% 			couchdb_repo: PS_RELATIONAL_REPOSITORY
% 		do
% 			print ("---o--- CouchDB Tutorial ---o---")
% 			io.new_line
% 			couchdb_repo := repo_factory.create_cdb_repository ("127.0.0.1", 5984)
% 			create executor.make (couchdb_repo)
% 			...
% \end{lstlisting}
% Instead of using \emph{repo\_factory.create\_in\_memory\_repository} we now use \newline
% \emph{repo\_factory.create\_cdb\_repository("127.0.0.1", 5984)}.
% Whereby the first argument of this method denotes the URL where the database is located (In this case we use the localhost) and the second argument is the used port (we use the default CouchDB port which is 5984). If for some reason your couch is not located on your own machine, you might have to adjust these values to point to the correct location.
% 
% If you compare the output of this tutorial to the output you got when using the in-memory database you might notice that nothing changed. On the surface both these databases provide the same services. Namely storing Eiffel objects.
% 
% \section{Beneath the surface}
% 
% Using CouchDB, Eiffel can store objects on a persistent database that can also be accessed by other programs. If not deleted, the data will persist after your program has ended.
% To accomplish this, ABEL will convert Eiffel objects to JSON documents, whereby each attribute will get its own \emph{"name": "value"} pair. The resulting document for a person will look similar to \emph{Listing 7.1}. After running the tutorial, the stored objects can also be explored by visiting \emph{127.0.0.1:5984/\_utils}.
% 
% You will notice that for both person and child a sub-database was created. The person database will only contain person-objects and the child database will only contain child-objects.
% If you don't want your data to remain in the database after the program has ended, insert a \emph{couchdb\_repo.wipe\_out} at the end of the feature explore
% 
% \section{Limitations}
% 
% CouchDB is not meant to be a relational database: it can nicely store objects as JSON Documents, that can then be searched by key. 
% CouchDB was mainly developed for the world wide web. For its basic API it uses cURL which is really easy to use but for its more advanced features like map-reduce it uses JavaScript. Map-reduce would come in handy when querying for objects in the database but it is not yet integrated and therefore for queries rather than using the inbuilt map-reduce of CouchDB ABEL uses an Eiffel function to accomplish the same. 
% 
% For more information on CoachDB see the online documentation.



%\chapter{Technical documentation}
%\input{technical_documentation}

%\chapter{Conclusions}
%\input{conclusions}

% \begin{flushleft}
%  
% {{{
% \bibliographystyle {plain}
% \bibliography {./references}
% }}}
% \end{flushleft}
\end{document}