\input epsf %  -*-texinfo-*-
\input texinfo

@c %**start of header
@settitle GNUstep Database Library Manual
@setfilename gdl.info
@c %**end of header

@setchapternewpage odd

@set version 1.0
@set update-month February 1997

@ifinfo
@format
START-INFO-DIR-ENTRY
* GDL::                      The GNUstep Database Library.
END-INFO-DIR-ENTRY
@end format
@end ifinfo

@ifinfo
This file documents the features of the GNUstep Database Library.

Copyright (C) 1997 NET-Community

@sp 1
While every precaution has been taken in the preparation of this book,
the publisher assumes no responsibility for errors or omissions, or for
damages from the use of the information contained herein.

The GNUstep Database Library Manual may be reproduced and distributed
in whole or in part, in any medium, physical or electronic, so long
as this copyright notice remains intact and unchanged on all copies.
Commercial redistribution is permitted and encouraged, but you may not
redistribute it, in whole or in part, under terms more restrictive
than those under which you received it.

@ignore
Permission is granted to process this file through @TeX{} and print the
results, provided the printed document carries copying permission
notice identical to this one except for the removal of this paragraph
(this paragraph not being relevant to the printed manual).

@end ignore

@end ifinfo

@iftex
@finalout
@smallbook
@end iftex

@setchapternewpage odd

@titlepage
@title GNUstep Database Library Manual
@subtitle Version @value{version}
@subtitle @value{update-month}
@author by Ovidiu C. Predescu and Mircea I. Oancea
@page

@vskip 0pt plus 1filll
Copyright @copyright{} 1997 NET-Community

@sp 1

While every precaution has been taken in the preparation of this book,
the publisher assumes no responsibility for errors or omissions, or for
damages from the use of the information contained herein.

The GNUstep Database Library Manual may be reproduced and distributed
in whole or in part, in any medium, physical or electronic, so long
as this copyright notice remains intact and unchanged on all copies.
Commercial redistribution is permitted and encouraged, but you may not
redistribute it, in whole or in part, under terms more restrictive
than those under which you received it.

@end titlepage

@tex
\global\parindent 0pt
\global\parskip 8pt plus 2pt
@end tex


@defcodeindex cl

@node Top, Introduction, (dir), (dir)

@menu
* Introduction::                General info about the GNUstep Database Library
* The model::                   How to describe the way your data is organized
* The adaptor level::           The adaptor level
* Creating an adaptor::         
* The database level::          The database level
* Writing a new adaptor::       How to write new adaptors
* The complete model::          The complete example of a model
* Concept Index::               Concept index of this documentation
* Classes Index::               Classes used in GDL
@end menu



@c =========================================================================
@c =========================================================================
@node	 Introduction, The model, Top, Top
@comment node-name, next, previous, up
@chapter Introduction

Programs that need to access a database may use the library provided by
the database vendor to send commands and retrieve the results from
database. This aproach is adequate for small programs. If you intend to
write a big program you usually create another layer on top of this
database library. The purpose of this layer is to transform the details
of lower level programming into some higher abstractions that are more
appropiate for your application. For example if you write an
object-oriented application you may want to pack the data in objects.

If the program is large you access the same tables from different parts
of the program then several objects containing the same data will
appear. These objects should be kept consistent with each other or
paradoxes in data values will appear in program. This means that at
every modification of the data should be made in all the objects that
contain it.

Some other abstractions can be imagined further. For example if your
program has a windowing interface, a common method of displaying data is
in what is called a master-detail view. Suppose you have a table in
which you display department names and when you select one of them, all
the persons that are in that department appear in another view. By
creating such a paradigm you can reuse it in all the parts of your
program that use it.

On top of this last abstraction you can further create other
abstractions that are specific to your application. By structuring your
application in such layers of abstractions you can create a much more
robust application than if you write it using directly the database
access library. In addition your application becomes easy to extend with
new features and of course much more easy to maintain.

@cindex master-detail

The GNUstep Database Library (GDL) offers you a well structured way to
build your application. It maps the database records into your own
objects, it automatically maintains them uniquely throughout your
program and helps you to create control layer abstractions using
master-details views and undo engines for the interface interaction. GDL
is database independent; you can use any database you want if you have
an adaptor for it. GDL does not come with a database server nor it is a
database server, but it has a clearly defined adaptor level which
communicates with specific DBMS.

GDL is structured in several levels that provide increasing higher of
abstractions. You can program your application at whatever level you
need; the library does not impose you any restriction on this. Usually
you may need to program at the lower levels only when the higher levels
don't offer you the functionality you want.

@iftex
@epsffile{layers.eps}
@end iftex
@center Figure 1. The various layers of the GDL.

@menu
* Application Objects::         
* The access layer::            
* The datasource::              
* The control layer::           
* gnustep-base ::               
* organization ::               
@end menu

@c =========================================================================
@node Application Objects, The access layer, Introduction, Introduction
@comment  node-name,  next,  previous,  up
@section Application Objects

@cindex Application Object

Let's imagine a simple human resources application to be written.  We
have a set of people, presumably employees, and we have some personal
and company-related data associated with each person.  An example of
such data would be the person's last name, first name, and the
department in which they work.

When writing database programs, it is desirable to design the program
based upon the business processes and the flow of information through
your organization.  This design is independent upon how data will be
physically stored and how it will be displayed to the end-user.  The GDL
uses the concept of Application Objects to create a model of your
business information that closely corresponds to your business
processes; then you create a mapping from your application objects to
the actual database data.  The point of this approach is easy to see;
programs can be designed and implemented based upon the needs of the
business, and underlying changes in the physical database storage is
easily handled by adjusting the mapping; leaving your business model
intact.

The above example involves two Application Objects: the Person and the
Department.  In @ref{The model}, you will see how the model of your
Application Objects is created, and how they are mapped to the physical
datastore.


@c =========================================================================
@node The access layer, The datasource, Application Objects, Introduction
@comment  node-name,  next,  previous,  up
@section The Access Layer

@cindex access layer

GDL comes with a powerful datasource and related classes designed to be
used use with relational databases. This layer consists of the
following:

@itemize @bullet

@item
@cindex adaptor level
The @emph{adaptor level} maps the records from the database into
dictionaries. This is the lower level of abstraction and it is dependent
on the database server you use.

@item
@cindex database level
The @emph{database level} creates Application Objects from the
dictionaries received from the adaptor level.

@item
@cindex model
The @emph{model} is used by the adaptor and database levels to store
information about how the records should be mapped into Application
Objects.

@item
@cindex database datasource
The @emph{database datasource} is a concrete implementation of the
datasource protocol for relational databases.

@end itemize


@c =========================================================================
@node The datasource, The control layer, The access layer, Introduction
@comment  node-name,  next,  previous,  up
@section The Datasource

@cindex datasource

Application Objects are retrived from and stored to a
@emph{datasource}. The datasource is a source for Application Objects,
either new ones --- fresh new object created at your request --- or for
old ones --- ones that you've created and used in the past and then
you've saved for a later use.

The datasource is an abstract interface; it does not specify anything
about the support used to store the Application Objects persistently. You
can imagine several different supports used for different types of
datasources: databases, flat files, DBM files or anything else that can
be used to store data persistently.

The datasource interface does provide only methods for creating new
objects, inserting, deleting, updating and retrieving them from the
persistent support.


@c =========================================================================
@node The control layer, gnustep-base , The datasource, Introduction
@comment  node-name,  next,  previous,  up
@section The Control Layer

@cindex control layer

// TODO

The control layer deals with the Application Objects from a
datasource. It uses a datasource to retrieve and modify Application
Objects.

@c =========================================================================
@node gnustep-base , organization , The control layer, Introduction
@comment  node-name,  next,  previous,  up
@section The GNUstep Base Library and the GNUstep Database Library

@cindex gnustep-base

The classes in the GNUstep Database Library are based upon and heavily
utilize the classes in the GNUstep Base Library.  The GNUstep Base
Library is a large collection of Objective-C classes that encapsulate
fundamental datatypes like strings, numbers, date and time; it also
contains numerous general purpose data structures like arrays,
dictionaries, and sets.  For complete information about rhe GNUstep
Database Library please @xref{Top,,Introduction,gnustep-base, The GNUstep
Base Library Manual}.

The classes must used by the GNUstep Database Library are:

@table @strong

@item NSArray
An ordered list of objects.

@item NSCalendarDate
Date and time objects with time zone information.

@item NSData
Encapsulation of an arbitrary block of binary data.

@item NSDictionary
Collection of key-value pairs.

@item NSNumber
Encapsulation of C scalar datatypes like float, double, and integer.

@item NSString
Encapsulation of character strings.

@end table

@c =========================================================================
@node organization ,  , gnustep-base , Introduction
@comment  node-name,  next,  previous,  up
@section Organization of the Manual

This manual is directed towards the programmer or technical manager who
will be directly involved in design, implementation, maintenance and/or
management of programs written with the GNUstep Database Library.  The
organization of the manual provides initial introductory material about
a subject then gets involved with explicity programming issues and
techniques.

Here is an overview of the remaining chapters.

@itemize @bullet

@item
@ref{The model} discusses Entity-Relationship modelling; how
to use it to model your Application Objects, and the GNUstep Database
Library classes that support such models.

@end itemize

@c =========================================================================
@c =========================================================================
@node The model, The adaptor level, Introduction, Top
@comment node-name, next, previous, up
@chapter The Model

The model represents the organization of your Application Objects'
classes and how it relates to the data in the database. It describes
what is the relation between these objects rather than describing the
strict organization of your database tables. The model does not
necessary follow the exact organization of your database. You can
imagine different models based on a database structure, depending on
your application demands.

@cindex Entity-Relationship modeling

You describe the model using the @emph{Entity-Relationship
modeling}. Entity-Relationship modeling uses @emph{entities},
@emph{attributes} and @emph{relationships} to describe the organization
of the data. In a relational database, entities represent tables and an
entity's attribute represent a table's column, though not all the
columns can be mapped in attributes for a given entity.

If we have the @code{Person} table in a database, we can associate it
with the @code{Person} entity. If the table has @code{firstName},
@code{lastName} and @code{picture} as columns we can associate those
columns attributes with the same names.

@cindex derived attribute

You can create attributes that don't exist in the entity's table. For
example you might want to compute the anual salary of a person from its
month salary by multiplying it by twelve. These attributes are called
@emph{derived attributes}.

@cindex flattened attribute

GDL extends the usual Entity-Relationship model by allowing you to add
to an entity attributes that are part of another entity. These
attributes are called @emph{flattened attributes}.

@cindex relationship

In the Entity-Relationship model in addition to entities and attributes
you also describe @emph{relationships} between entities. A relationship
describes the logical relation that exists between two entities. In our
example the @b{Department} entity has a relationship of which @b{Person}s
belong to that department.

Application Objects are the basic units on which the database operations
are made. Retrieving, updating, inserting and deleting operations are
perfomed on Application Objects. Each Application Object class should be
described by an entity. So an entity has associated with it the
Application Object class used by the database level to create instances.

The attributes of an entity are mapped into instance variables of
Application Objects. The instance variables could be of an object type or
other elementary Objective-C types. Since values are returned by the
adaptor level in a dictionary and they are of an object type, GDL
automatically translates object values to an elementary Objective-C type
if needed.

A model is described in a file in the property-list format. The model
file is read at run-time when the application creates the database or
adaptor objects. Your program generally doesn't manipulate the model
directly unless you want to change it dinamically. The format of the
model file is described in the further sections.

The classes used to represent a model are @code{EOModel},
@code{EOEntity}, @code{EOAttribute}, @code{EORelationship} and
@code{EOJoin}. In the following we will detail the model classes.

@iftex
Figure 2. shows the relation between the model classes. The
arrows between classes represent the relations between their
instances. A single arrow from a box to another means that each
corresponding instance of the class in first box has one instance of the
corresponding class in the second box. A double arrow means the first
instance has an array of instances corresponding to the second box. For
example the singe arrow from @code{EOAttribute} to @code{EOEntity}
means that every @code{EOAttribute} has a corresponding @code{EOEntity}
instance. The double arrow from @code{EOEntity} to @code{EOAttribute}
means that every @code{EOEntity} instance has an array of
@code{EOAttribute} instances.

@sp 2

@epsffile{model.eps}
@end iftex
@center Figure 2. Relationship between the model classes.

@menu
* eomodel::                     
* Attributes::                  
* Relationships::               
* Entities::                    
* A complete model::            
* Resolving cycles within your model. A garbage collector::  
@end menu


@c =========================================================================
@node eomodel, Attributes, The model, The model
@comment  node-name,  next,  previous,  up
@section EOModel

The @code{EOModel} class represents the model of all your Application
objects; generally a program will just have a single model, but it is
possible to have multiple models if desired.  For example, an
organization may put Payroll and Human Resource Application Objects
together into a single model because of the large overlap in the two
business processes.  However, another organization may wish to separate
them into two models; each model only containing Application Objects
which represents the information needed from the other model.  Using two
separate models allows you to explicitly model what Payroll information
Human Resources is allowed to see and vice-versa.

@subsection Loading a Model File

Models can be stored in text files and loaded upon execution of a
program.  Storing the model in a file allows external programs to be
used for parsing and maintaining your models separate from your
programs.  The GNUstep Interface Modeller application is an example.

The @code{-initWithContentsOfFile:} method is used to initialize a newly
allocated EOModel instance with the contents of a file; the following
code sample shows its use.

@smallexample
NSString *modelPath;
EOModel *humanResourceModel;

modelPath = [EOModel findPathForModelNamed: @"HumanResource"];
humanResourceModel = [[EOModel alloc] initWithContentsOfFile: modelPath];
@end smallexample

The @code{+findPathForModelNamed:} method searches a series of
directories to find the model file.  It first searches the application's
main bundle directory, then the user's home library directory
(~/Library/Models), and lastly the GNUstep Database Library directory
($GNUSTEP_DB_LIBDIR/Models).  Other directories may be searched based
upon your local GNUstep setup.  @code{+findPathForModelNamed:} attaches
the extension @samp{.eomodel} onto the name to produce the complete
filename.

@subsection Creating a Model from the Database Schema

The @code{EOAdaptorChannel} class has the methods
@code{-describeTableNames} and @code{-describeModelWithTableName:} that
can be used to construct a model based upon the current database schema.
It is necessary for you to have a valid connection to the database
before using these methods; the following code sample shows how to
create a model for all of the tables in the database.

@smallexample
EOAdaptorChannel *myChannel;   /* this already exists */
EOModel *myModel;

myModel = [myChannel describeModelWithTableName:
                [myChannel describeTableNames]];
@end smallexample

The model may or may not be able to construct relationships between
tables based upon whether that data is available from the database
schema.

@subsection Programmatically Creating a Model

It is also possible to construct a model programmatically; an example
where this may be necessary is if the actual model is dependent upon
data values in the database and cannot be know ahead of time.

Use @code{-initWithName:} to initialize an @code{EOModel} instance and
assign it a name.  Then use @code{-addEntity:} to add EOEntity instances
to your model.  You must also set the name of the adaptor class with
@code{-setAdaptorName:} and set the connection dictionary with
@code{-setConnectionDictionary:} before you attempt to use the model.

@subsection Merging Models

@code{-incorporateModel:} is a method that can be used to completely
incorporate one model with all of its entities into a receiving model.
The method returns YES if successful or NO if there are conflicts
between the two models.  Possible conflicts are identically named
elements that do not match in structure or if the models use different
adaptors.  Incorporation of a model does not affect the connection
dictionary of the receiving model.

The model that is incorporated is disposed, so if you wish to still use
that model after incorporation; then create a copy of the model and
incorporate that copy.

@subsection Property List Representation of a Model

As indicated earlier, models are stored as property lists in text files.
A property list is a textual representation of NSDictionary, NSArray,
NSString, and NSData object.

You can request a model to return its complete schema as a property list
(within an NSString) with @code{-modelAsPropertyList}; the following
code sample shows how to write out a model to a file.

@smallexample
EOModel *myModel;  /* this already exists */
NSString *propertyList;

propertyList = [myModel modelAsPropertyList];
[propertyList writeToFile: @@"TheModel.eomodel" atomically: YES];
@end smallexample

@code{EOModel} also has the @code{-initWithPropertyList} method which
initializes a newly allocated EOModel with the contents of a property
list; the following code sample shows how to create a copy of a model.

@smallexample
EOModel *originalModel;  /* this already exists */
EOModel *modelCopy;

modelCopy = [[EOModel alloc] initWithPropertyList:
                [originalModel modelAsPropertyList]];
@end smallexample

@subsection Additional EOModel Methods

@code{-path} returns the full path of the file used to initialize the
@code{EOModel} instance; this includes the directory, filename, and file
extension.  the method returns nil if the model was not initialized from
a file.

@code{-name} returns the model name.

@code{-adaptorName} returns the name of the adaptor class for the model.

@code{-connectionDictionary} returns the connection dictionary
associated with the model; the returned dictionary is immutable so you
must use an appropriate @code{-setConnectionDictionary:} method in
@code{EOModel} or @code{EOAdaptor} to change the connection dictionary.

@code{-entity} returns an @code{NSArray} containing all of the model's
@code{EOEntities}.

@code{-entityForObject:} returns the entity for an Application Object.

@code{-entityNamed:} returns the @code{EOEntity} in the model with the
specified name.

@code{-referencesToProperty:} returns an array of all properties, such
as @code{EOAttribute} and @code{EORelationship}, that reference the
property in the model.

@code{-userDictionary:} and @code{-setUserDictionary:} are used to
return and set the dictionary of user data; this dictionary can be used
by the application to store any auxiliary information related to the
model.

@c =========================================================================
@node Attributes, Relationships, eomodel, The model
@comment  node-name,  next,  previous,  up
@section Attributes

@clindex EOAttribute

An attribute is an instance of the @code{EOAttribute} class. An
attribute could be @emph{simple}, @emph{derived} or @code{flattened}.

@cindex simple attribute

A simple attribute is one that maps directly over a column from the
table. @b{firstName}, @b{lastName} and @b{picture} are examples
of simple attributes.

@cindex derived attribute

A derived attribute is an expression that depends on other attributes
from entity. For example @code{salary * 12} is a derived attribute.

@cindex flattened attribute

A flattened attribute is a mapping of an attribute from another
entity. If the @b{Department} entity has a to-one relationship to the
@b{Person} that is the chief of department, then we can arrange to
have two flattened attributes @b{firstName} and @b{lastName} that
represent the name of the chief. In order to be able to do this we have
to create a to-one relationship to the @b{Person}
entity. @pxref{Relationships} for more information about
relationships. It is an error to specify flattened attributes using
relationships that are not to-one.

You can declare a flattened attribute by specifying the whole path to
the attribute. For example if @b{toBoss} is the relationship in
@b{Department} that specifies the chief of the department; then we can
define the two above flattened attributes by @code{toBoss.firstName} and
@code{toBoss.lastName}.

Flattened attributes can be defined over several relationships. Suppose
we have three entities @b{A}, @b{B} and @b{C} and the to-one
relationships @b{toB} in A and @b{toC} in @b{B} and @b{c} is an
attribute of @b{C}. Then we can define in @b{A} a flattened attribute
@b{c} whose definition is @code{toB.toC.c}. Note that both relationships
must be defined as to-one.

If the attribute is simple you should specify the name of the column it
represents and the external type of the column. The external type is
dependent on the database server you use so if you want to use the model
with another database server you have to change the type accordingly.

When the adaptor retrieves records from a table corresponding to an
entity, it creates values for each attribute from entity. These values
are instances of the class you specify for attribute. If this class is
@code{NSNumber} you can also specify the type of the value. When the
adaptor executes other operations such as updates or insertions, it
converts the values from dictionaries into the proper values needed by
the database as specified in the external type. You can also create your
own value classes and interpret the value type as you wish.

An attribute has a name associated with it which identifies it within
its entity. The attributes names have to be unique within an entity. If
the attribute is simple the name could be different than the column name
it represents.

A simple attribute is specified in the model file like below:

@example
@group
@{
    columnName = first_name;
    externalType = varchar;
    name = firstName;
    valueClassName = NSString;
@}
@end group
@end example

A derived attribute is specified like in the below example. The names
that appear as attributes in the definition should be valid attribute
names even if they are from other entities as long as the relationships
path to them exist. Any other names that appear are left unmodified. The
names that can appear in the definition should be attribute names and
not external names, otherwise the generated SQL SELECT expression can be
incorrect.

@example
@group
@{
    definition = "lastName + ',' + firstName";
    externalType = varchar;
    name = Name;
    valueClassName = NSString;
@}
@end group
@end example

Finally, a flattened attribute is declared like this:

@example
@group
@{
    definition = toBoss.lastName;
    name = BossName;
@}
@end group
@end example

You can also specify the type of a number under the key
@code{valueType}. The value types for @code{NSNumber} values can only be
one of the standard Objective-C encodings:

@table @code

@item c
char

@item C
unsigned char

@item s
short

@item S
unsigned short

@item i
int

@item I
unsigned int

@item l
long

@item L
unsigned long

@item f
float

@item d
double

@end table

If you use your own value classes you can specify anything you want as
value type as long as you handle it.


@c =========================================================================
@node Relationships, Entities, Attributes, The model
@comment  node-name,  next,  previous,  up
@section Relationships

@cindex relationship

A @emph{relationship} expresses the relation that exists between two
entities. In our previous simple model each department has a chief. This
relation is figured out by a relationship between @b{Department} and
@b{Person}, named @b{toBoss}.

When you define a relationship you have to decide what is the source
entity and what is the destination entity. You also have to specify
pairs of attributes from the two entities that are linked together. In
our example we can link together the @b{personId} attribute in the
@b{Department} entity and the @b{personId} attribute from the
@b{Person} entity.

@cindex primary key
@cindex foreign key

You can use whatever attributes you want to specify the link between the
two entities. However these attributes are usually chosen very carefuly
because they have to link unique objects; the attributes from the
destination entity are usually the primary key of the entity (@pxref{Primary keys}). When the attributes from the destination entity are
primary keys the attributes from the source entity are called
@emph{foreign keys}; the values for these attributes are the values of
the primary keys from the destination entity.

@menu
* Joins::                       
* Relationships cardinality::   
* Flattened relationships::     
* Many-to-many relationships::  
* Reflexive relationships::     
* Describing relationships::    
@end menu

@c =========================================================================
@node Joins, Relationships cardinality, Relationships, Relationships
@comment  node-name,  next,  previous,  up
@subsection Joins

@cindex join

The link between the source and destination attributes is specified as
we seen above by a set of attributes pairs. Each pair of attributes
together with the join operator and the join semantic, about which we
will discuss later, is called @emph{join}.

@cindex join operator
@cindex join condition

The join operator specifies the relation between the two attributes of
the join and can be one of the less than, less than or equal to, greater
than, greater than or equal to, equal to and not equal to operators. The
relation between the source and destination attributes through the join
operator is called @emph{join condition}.

@cindex join semantic

The join semantic tells how the tuples from the two entities are
selected. The possible join semantics are @footnote{Not all the database
servers support all types of join semantics. The inner join is usually
supported by all of them.}:

@itemize @bullet

@item @emph{inner join}: selects only the tuples that satisfy the
join condition.

@item @emph{full outer join}:
selects all the tuples even if the join attributes do not satisfy the
join condition.

@item @emph{left outer join}:
selects only the tuples whose source records have no corresponding
destination records.

@item @emph{right outer join}:
selects only the tuples whose destination records have no corresponding
source records.

@end itemize


@c =========================================================================
@node Relationships cardinality, Flattened relationships, Joins, Relationships
@comment  node-name,  next,  previous,  up
@subsection Relationship Cardinality

When you define a relationship it exists only between the source and
destination entities. If you need a reverse relationship you should
define another one in the destination entity. For example the
@b{Person} entity has a relationship @b{toDepartment} to the
@b{Department}. Another relationship @b{toPersons} exists
between the @b{Department} and @b{Person} entities.

@cindex relationship cardinality
@cindex to-one relationship

An important property of a relationship is its @emph{cardinality}. This
property is given by the number of destination records that corespond to
a given source record. If only one destination record is associated
through the join to a source record for all the records in the source
entity, the relationship is called to be a @emph{to-one}
relationship. In our example each @b{Person} has a unique
@b{Department} in which he or she works so the @b{toDepartment}
relationship is a to-one relationship.

@cindex to-many relationship

If more than one records in the destination entity are associated with a
source record for at least one record in the source entity, then the
relationship is called a @emph{to-many} relationship. The
@b{toPersons} relationship in the @b{Department} entity is an
example of a to-many relationship.


@c =========================================================================
@node Flattened relationships, Many-to-many relationships, Relationships cardinality, Relationships
@comment  node-name,  next,  previous,  up
@subsection Flattened Relationships

@cindex flattened relationship

The relationships we have seen so far were simple relationships. Each
one has a source entity and a destination entity and has joins that link
these entities. The GDL model allows you to specify relationships that
link two entities using other relationships. These relationships are
called @emph{flattened relationships}.

Suppose we have another entity called @b{Facility} which tells what
is the building where a department is. In a building we can possibly
have more the one department but we consider a department to be in a
single building. We can model this by adding a relationship
@b{toFacility} in the @b{Department} entity and a
@b{toDepartments} relationship in the @b{Facility} entity. Now if
we want to know in which building a @b{Person} is, we can create a
flattened relationship from @b{Person} to @b{Facility} called
@b{toFacility} to be @code{toDepartment.toFacility}. This definition
specifies the whole path to follow to reach the @b{Facility} entity.

A flattened relationship has the cardinality depending on the
relationships that compose it. If all the relationships are to-one then
the relationship is also to-one. If there is at least one relationship
that is to-many, the flattened relationship is to-many.

@c =========================================================================
@node Many-to-many relationships, Reflexive relationships, Flattened relationships, Relationships
@comment  node-name,  next,  previous,  up
@subsection Many-to-many Relationships

@cindex many-to-many relationship

In many problems is necessary to create some many-to-many relations
between two entities: each record from an entity has associated with it
more than one records from the other entity. For example suppose we have
the @b{Project} entity who keeps all the projects in work. A
@b{Project} has many people who work on it. Also suppose that a
people can be involved in more than one project.

To allow such a behavior another entity has to be introduced. This
entity keeps two to-many relationships: one to first entity and one for
the second entity. The source attributes of these relationships are the
primary keys of the entities. In our example we can introduce the
@b{PersonProject} entity whose attributes are the @b{personId} and
@b{projectId} attributes. The related relationships are
@b{toPerson} and @b{toProjects} respectively.

@c =========================================================================
@node Reflexive relationships, Describing relationships, Many-to-many relationships, Relationships
@comment  node-name,  next,  previous,  up
@subsection Reflexive Relationships

@cindex reflexive relationship

You can define relationships whose source and destination entities are
the same. This kind of relationships is called @emph{reflexive
relationships}. For example we can define a relationship @b{toBoss}
whose foreign key @b{bossId} is the id of the person who is the chief
of a given person. The persons who don't have a chief have the
@b{bossId} attribute set to @code{NULL} to indicate this.

A person who is chief can in turn have its own chief. This way the
dynamic chain of chiefs can be arbitrarly long and is not limited to the
static definition of the @b{toBoss} definition.

The reflexive relationships are not limited to to-one relationships;
to-many reflexive relationships can be imagined as well.

@c =========================================================================
@node Describing relationships,  , Reflexive relationships, Relationships
@comment  node-name,  next,  previous,  up
@subsection Describing Relationships

@clindex EORelationship

Relationships are described for a given entity. In GDL the class used to
represent relationships is @code{EORelationship}. See the description of
this class for more info.

In the model file all the relationships of an entity can be accessed
from the entity's dictionary under the key @code{relationships}. The
value associated is an array of relationships.

A relationship has the following properties:

@itemize @bullet

@item
the name of relationship under the key @code{name} (the value should be
@code{NSString}).

@item
the name of the destination entity under the key @code{destination} (the
value should be @code{NSString}).

@item
an array of join descriptions.

@item
a boolean that specifies if the relationship is to-many or not under the
key @code{isToMany} (the value should be @code{Y} or @code{N}).

@end itemize

A join description is a dictionary containing the following properties:

@itemize @bullet

@item
the source attribute name under the key @code{sourceAttribute} (the
value should be a @code{NSString}).

@item
the destination attribute name under the key @code{destinationAttribute} (the
value should be a @code{NSString}).

@item
the name of the join operator under the key @code{joinOperator}. The
possible values for this are:

@itemize @minus

@item @code{EOJoinEqualTo},
@item @code{EOJoinNotEqualTo}
@item @code{EOJoinGreaterThan}
@item @code{EOJoinGreaterThanOrEqualTo}
@item @code{EOJoinLessThan}
@item @code{EOJoinLessThanOrEqualTo}.

@end itemize

@item
the name of the join semantic. The possible values for this are:

@itemize @minus

@item @code{EOInnerJoin}
@item @code{EOFullOuterJoin}
@item @code{EOLeftOuterJoin}
@item @code{EORightOuterJoin}

@end itemize

@end itemize

Example:

@example
relationships = (
    @{
        destination = Department;
        isToMany = N;
        joins = (
            @{
                destinationAttribute = deptId;
                joinOperator = EOJoinEqualTo;
                joinSemantic = EOInnerJoin;
                sourceAttribute = deptId;
            @}
        );
        name = toDepartment;
    @},
    @{
        destination = Person;
        isToMany = N;
        joins = (
            @{
                destinationAttribute = personId;
                joinOperator = EOJoinEqualTo;
                joinSemantic = EOInnerJoin;
                sourceAttribute = bossId;
            @}
        );
        name = toBoss;
    @}
);
@end example

If the relationship is flattened you have to specify only the name of
the relationship and its definition. The definition of relationship is
specified under the key @code{definition}.

Example:

@example
relationships = (
    @{
        definition = toDepartment.toFacility;
        name = toFacility;
    @}
);
@end example

@clindex EOJoin

A join is represented in the program by instances of @code{EOJoin}
class. See a description of this class for more information.

@c =========================================================================
@node Entities, A complete model, Relationships, The model
@comment  node-name,  next,  previous,  up
@section Entities

@clindex EOEntity

Entities describe how the records from a specific table from database map to Application Objects. An entity is described in GDL by an instance of @code{EOEntity} class. An entity has some attributes that describe the logic organization of data in a particular table and how is this organization represented in the Application Object as well as other internal attributes.

@itemize @bullet

@item the name of the entity

@item the class name of the Application Object

@item the name of the database table

@item its attributes

@item its relationships

@item the attributes used as primary keys

@item the attributes used as class properties

@item the attributes used for locking

@end itemize

@menu
* Primary keys::                
* Class properties::            
* Locking attributes::          
* Describing entities::         
@end menu

@c =========================================================================
@node Primary keys, Class properties, Entities, Entities
@comment  node-name,  next,  previous,  up
@subsection Primary Keys

@cindex primary keys

When you work with records in a table you usually want to make them distinct each other in order to later identify them uniquely. To do this you specify a set of attributes that make the records distinct. These attributes are called @emph{primary keys}.

For example the @b{personId} attribute from the @b{Person} entity can be used as primary key if its value is different for all the persons.

You should specify as primary keys only the minimal set of attributes that guarantees the records are distinct. Redundant attributes does not influence the uniquess of records but affect the speed of uniquing in the database level. Also you should avoid specifying as primary keys attributes having as types large binary data or big strings.

@c =========================================================================
@node Class properties, Locking attributes, Primary keys, Entities
@comment  node-name,  next,  previous,  up
@subsection Class properties

All the @code{EOAttribute}s in an @code{EOEntity} are usually needed to be represented in an Application Object. There are times however when you don't want to have an attribute represented in an Application Object because you use it only for locking or for specifying a relationship.

@cindex class property

You can specify a set of class properties that are to be represented in an Application Object. Only those attributes marked as class properties are represented in Application Objects.

@c =========================================================================
@node Locking attributes, Describing entities, Class properties, Entities
@comment  node-name,  next,  previous,  up
@subsection Locking Attributes

@cindex locking attributes

When the database level is configured to use optimistic locking (@pxref{Database Intro Uniquing}), it uses the the attributes specified as locking attributes in the qualifier of @code{UPDATE} operation to modify an Application Object. If the record in database corresponding to the Application Object has some of these attributes modified the @code{UPDATE} operation fails.

The attributes used for locking should not be necessary specified as class properties. The locking attributes are anyway retrieved from the database and if they are not class properties they will not be seen by the Application Object.

@c =========================================================================
@node Describing entities,  , Locking attributes, Entities
@comment  node-name,  next,  previous,  up
@subsection Describing Entities

An entity description is a dictionary containing these entries under the following keys:

@itemize @bullet

@item @code{name} -- the name of the entity

@item @code{className} -- the class name of the Application Object

@item @code{externalName} -- the name of the table from the database

@item @code{userDictionary} -- a dictionary that can be interpreted by the user application (optional)

@item @code{attributes} -- an array of @code{EOAttribute} descriptions

@item @code{primaryKeyAttributes} -- an array of attributes names used as primary keys

@item @code{classProperties} -- an array of attributes names used as class properties

@item @code{attributesUsedForLocking} -- an array of attributes names used for locking (optional if you don't use uniquing)

@item @code{relationships} -- an array of @code{EORelationship} descriptions (optional)

@end itemize

When you have to specify the attribute names in arrays you should use the name of the attribute not the external names.

@c =========================================================================
@node A complete model, Resolving cycles within your model. A garbage collector, Entities, The model
@comment  node-name,  next,  previous,  up
@section A Complete Model

@clindex EOModel

The model contains all the information we described so far. The class whose instances are used to describe models is @code{EOModel}. A model is described by a dictionary in which the following keys have meaning:

@itemize @bullet

@item @code{EOModelVersion} -- the version of the model file (current version is 1)

@item @code{adaptorName} -- the name of the adaptor

@item @code{adaptorClassName} -- the class name of the adaptor class (inherited from @code{EOAdaptor})

@item @code{connectionDictionary} -- a dictionary that contains information specific to each adaptor

@item @code{entities} -- an array that contains all the entities

@end itemize


Below is a figure that shows the whole example model described so far. A
box represents an entity and an arrow between two boxes represent a
relationship between the two entities: a single arrow is a to-one
relationship and a double arrow is a to-many relationship.

@iftex
@epsffile{example-model.eps}
@end iftex

The description of the model is given in @ref{The complete model}. The Sybase database is assumed but with small modifications the model can be easily transformed for any other database.

@c =========================================================================
@node Resolving cycles within your model. A garbage collector,  , A complete model, The model
@comment  node-name,  next,  previous,  up
@section Resolving cycles within your model. A garbage collector

While describing complex data structures you can do relatively easily cycles within your model. For example if we want to know what are the people who work into a @b{Department} we need a relation from @b{Department} to @b{Person}. In our model this creates a local cycle.

Because of the OpenStep Foundation ownership policy these kind of cycles make the objects implied in them to be leaks, because they never get deallocated.

To solve these situations we have come with a general solution that can also be applied to other problems into your program @footnote{The garbage collector is not part of the GDL itself, it comes with the FoundationExtensions library so it can be used in other programs as well.}. The solution is a garbage collector based on reference counting. This garbage collector is perfectly compatible with the well known retain/release policy from OpenStep.

@menu
* The algorithm::               
* The GarbageCollector class::  
* The GarbageCollecting protocol::  
* Support classes::             
* When do I need garbage collectable objects?::  
@end menu

@c =========================================================================
@node The algorithm, The GarbageCollector class, Resolving cycles within your model. A garbage collector, Resolving cycles within your model. A garbage collector
@comment  node-name,  next,  previous,  up
@subsection The algorithm

@cindex garbage collector

The garbage collector neither maintains explicitly all the pointers in your program nor it collects all the memory allocated by you in the program. Instead it collects and maintains only some special kind of objects, that are garbage collectable.

The algorithm was inspired from a similar one found in the Brian M. Kennedy's <bmk@@csc.ti.com> OATH C++ library. It works in three passes. Suppose that all the objects that are garbage collectable are known. Also each object has an additional flag, used for determining if the object was already visited.

During the first pass, all objects that are garbage collectable clears the associated flag and receive the message @code{-gcDecrementRefCountOfContainedObjects}. In this method the object decrements the ref count of every garbage collectable object it contains. After this pass all the objects that have the ref count 0 are part of cyclic graphs. Such objects have their ref count due only to another objects from graph.

In the second pass we have to restore the original ref counts and to isolate the nodes from cyclic graphs. In this pass all the objects that have the ref count greater than 0 receive the message @code{-gcIncrementRefCountOfContainedObjects}. In this method the object check the flag if it's set. This flag tells if the object was visited previously. If the flag is set, the method returns, else the flag is set. Then the ref count of every garbage collectable object contained is incremented and the message @code{-gcIncrementRefCountOfContainedObjects} is sent to those objects.

After this pass all the objects that are reachable from `outside' have their ref count greater than 0. All the objects that still have their ref count equal with 0 are part of cyclic graphs and there is no reference from `outside' to an object from these graphs.

In the third pass all the objects that have their ref count equal with 0 receive the @code{-dealloc} message. In this method the objects should send the @code{-release} message to all contained objects that are not garbage collectable. This because the order of deallocation is not known and you can send @code{-release} to an already deallocated object. So if a class contains both normal objects and garbage collectable objects, it should maintain their collectable status when the objects are retained.

@c =========================================================================
@node The GarbageCollector class, The GarbageCollecting protocol, The algorithm, Resolving cycles within your model. A garbage collector
@comment  node-name,  next,  previous,  up
@subsection The @code{GarbageCollector} class

@clindex GarbageCollector

The class @code{GarbageCollector} implements the garbage collector. It has the following interface:

@example
@@interface GarbageCollector : NSObject

+ (void)addObject:(id)anObject;
+ (void)objectWillBeDeallocated:(id)anObject;

+ (void)collectGarbages;

@@end
@end example

A new garbage collectable object has to be made know to the @code{GarbageCollector} collector by sending it the @code{+addObject:} message with self as argument. When the object is deallocated it should inform the @code{GarbageCollector} class about this by sending it the @code{+objectWillBeDeallocated:} message with self as argument.

The @code{+collectGarbages} should be send to the @code{GarbageCollector} class to collect the garbages. You can send it whenever you want. If you are using a run loop in your program you can set a timer to be called periodically. Or you can call the garbage collector when the program is idle.

In the current implementation the garbage collector is not thread-safe, so please don't use it in multi-threaded programs, unless you use garbage collectable objects only in one thread.


@c =========================================================================
@node The GarbageCollecting protocol, Support classes, The GarbageCollector class, Resolving cycles within your model. A garbage collector
@comment  node-name,  next,  previous,  up
@subsection The @code{GarbageCollecting} protocol

To allow instances of a class to be garbage collectable, the class should implement the following protocol:

@clindex GarbageCollecting

@example
@@protocol GarbageCollecting

- gcSetNextObject:(id)anObject;
- gcSetPreviousObject:(id)anObject;
- (id)gcNextObject;
- (id)gcPreviousObject;

- (void)gcIncrementRefCount;
- (void)gcDecrementRefCount;

- (void)gcDecrementRefCountOfContainedObjects;
- (BOOL)gcIncrementRefCountOfContainedObjects;

- (BOOL)isGarbageCollectable;

@@end
@end example

The @code{GarbageCollector} class uses a double linked list to maintain the objects. The @code{gcSetNextObject:}, @code{gcSetPreviousObject:}, @code{gcNextObject} and @code{gcPreviousObject} are used by the collector to add or remove objects in its list. This could change in the future.

The @code{gcIncrementRefCount} and @code{gcDecrementRefCount} methods should increment, respectively decrement the ref count of receiver.

The @code{gcDecrementRefCountOfContainedObjects} method should decrement the ref count of all garbage collectable objects contained, by sending them the @code{-gcDecrementRefCount}.

The @code{gcIncrementRefCountOfContainedObjects} method should check the flag. If this is true, the method should return @code{NO}; it this is false the method should set it. Then it should increment the ref count of garbage collectable objects contained by sending them the @code{-gcIncrementRefCount} message. After this it should send the @code{-gcIncrementRefCountOfContainedObjects} message to the same objects. Then it should return @code{YES}.

The object should respond @code{YES} at the @code{-isGarbageCollectable} message if it is garbage collectable. The NSObject class responds @code{NO} to this message.

You should note the asymmetry between the @code{gcDecrementRefCountOfContainedObjects} and @code{gcIncrementRefCountOfContainedObjects} methods. This makes the algorithm to work. So be careful if you're using copy/paste operations to write them in your editor :-)!


@c =========================================================================
@node Support classes, When do I need garbage collectable objects?, The GarbageCollecting protocol, Resolving cycles within your model. A garbage collector
@comment  node-name,  next,  previous,  up
@subsection Support classes

There is a class @code{GCObject} from which you could inherit your own classes. This class implements the @code{GarbageCollecting} protocol. 

Using this class, you could write a class whose instances hold other objects. This class is safe to cyclic references. Here is its implementation:

@example
@@interface MyGCObject : GCObject
@{
    id object;
    BOOL isGarbageCollectable;
@}

- (void)setObject:(id)anObject;
- (id)object;

@@end


@@implementation MyGCObject

- (void)setObject:(id)anObject
@{
    [anObject retain];
    [object release];
    object = anObject;
    isGarbageCollectable = [object isGarbageCollectable];
@}

- (id)object
@{
    return object;
@}

- (void)decrementRefCountOfContainedObjects
@{
    [object gcDecrementRefCount];
@}

- (BOOL)incrementRefCountOfContainedObjects
@{
    if(![super incrementRefCountOfContainedObjects])
        return NO;
    [object gcIncrementRefCount];
    [object incrementRefCountOfContainedObjects];
    return YES;
@}

- (void)dealloc
@{
    if(!isGarbageCollectable)
        [object release];
    [super dealloc];
@}

@@end
@end example

@clindex GCArray
@clindex GCMutableArray
@clindex GCDictionary
@clindex GCMutableDictionary

There are also concrete subclasses of @code{NSArray} and @code{NSDictionary} named @code{GCArray} and @code{GCDictionary} respectively, together with their mutable classes @code{GCMutableArray} and @code{GCMutableDictionary}. Their instances could hold both normal and garbage collectable objects.

If you don't want to write your own Application Object you can use the @code{GCGenericRecord} class that is similar with @code{EOGenericRecord} but works correctly in case of cycles.

@c =========================================================================
@node When do I need garbage collectable objects?,  , Support classes, Resolving cycles within your model. A garbage collector
@comment  node-name,  next,  previous,  up
@subsection When do I need garbage collectable objects?

The algorithm is not working if the cycles is interrupted in one place. So to assure it works correct you'll have to make all the objects part of a cycle to be garbage collectable.

An object that is garbage collectable behaves like a normal object with respect to retain/release messages, so it will be deallocated as usual if it is not part of a cycle. The only overhead implied is that it will participate in the garbage collection algorithm if one occurs while the object is alive.


@c =========================================================================
@c =========================================================================
@node The adaptor level, Creating an adaptor, The model, Top
@comment node-name, next, previous, up
@chapter The Adaptor Level

@cindex adaptor level

The Adaptor Level is the lowest level in GDL and only it deals with the details of accessing each specific database server. The Database Level which is above it uses its methods to perform all of its database operations.

The Adaptor Level is composed from four classes:

@table @code

@clindex EOAdaptor
@item EOAdaptor

It represents a database from the database server and it keeps the model and the connection dictionary. All the server specific formatting of SQL expressions is performed here.

An adaptor instance keeps a list of adaptor contexts which are used to represent several database transaction scopes on the database.

@clindex EOAdaptorContext
@item EOAdaptorContext

Instances of this class represent a unique transaction scope within database server. However if the database server allows nested transactions other transactions can be nested inside the original one.

An adaptor context has a list of adaptor channels that represent distinct operation channels within the same transaction. Concrete adaptors may not support more than one channel per context.

@clindex EOAdaptorChannel
@item EOAdaptorChannel

This is the class that actually keeps a connection with the database server. It executes all the select, insert, update and delete operations within database. The @code{EOAdaptorChannel} maps the records from the database into dictionary rows that are further passed to the Database Level.

@clindex EOSQLExpression
@item EOSQLExpression

This class is used to generate the SQL operations. It knows how to generate the four basic SQL operations: select, insert, update and delete. You normally do not use directly this class, it is used internally by the adaptor classes.

@end table

@c =========================================================================
@node Creating an adaptor, The database level, The adaptor level, Top
@comment node-name, next, previous, up
@chapter Creating an Adaptor



@c =========================================================================
@c =========================================================================
@node The database level, Writing a new adaptor, Creating an adaptor, Top
@comment node-name, next, previous, up
@chapter The Database Level

@cindex database level

The Database Level main purpose is to offer an Object Oriented access to a
relational database maintained by a specialized SQL data server like
Sybase, Informix or Oracle.  The Adaptor Level manipulates data as rows
(@code{NSDictionary} instances) from tables while the Database Level uses
Application Objects (instances of user defined classes) that store the row
data, implement user defined behavior and automatically resolve
relationships. 

The Database Level uses the Adaptor Level to perform its operations with
the SQL data servers. For users that need not concern about working with
the Adaptor Level, Database Level objects hide the Adaptor Level by
creating and using the Adaptor Level objects they need. However, users that
want to perform low level operations available only in the Adaptor Level,
can access these objects and work with them as usual.   

Its main features are:

@itemize @bullet

@item operates in terms of Application Objects compared to the Adaptor
Level that operates in terms of rows (@code{NSDictionary} instances).

@cindex application object, property access
@cindex property access
@item provide an uniform access to Application Objects properties through
the @code{EOKeyValueCoding} informal protocol (category of
@code{NSObject}).  

@cindex database, mapping rows to objects
@cindex mapping of rows
@item mapping from rows to Application Objects and back from objects to rows.

@cindex database, uniquing
@cindex uniquing rows
@item uniquing of rows based on primary keys, so that multiple fetches of
the same row go to the same object. 

@cindex database, resolve relationships
@cindex relationship resolution
@item delayed relationship resolution.

@cindex database, transaction
@cindex database, locking
@cindex database, updates
@item provide several strategies to lock objects into the data server for
update operations by using the dataserver locking features or by using
snapshots (the latest known state of a row). 

@item creation and management of Adaptor Level objects; for operations not
available in the Database Level users can access the adaptor objects and
work with them.

@end itemize 

@menu
* Database Introduction::       General info about GDL Database Level
* Database Features::           Describes key features of the Database Level
* Database Using::              Using the Database Level
@end menu

@c ============================================================================
@node Database Introduction, Database Features, The database level, The database level
@comment  node-name,  next,  previous,  up
@section Database Introduction

This section provides an introduction to the features of the Database
Level. Some of these features are fully explained in @ref{Database
Features}. 

@menu
* Database Intro Classes::      Classes in the Database Level
* Database Intro Properties access::  Uniform properties access
* Mapping from rows to objects::  Mapping from rows to objects
* Database Intro Uniquing::     Uniquing
* Database Intro Relationships::  Delayed relationship resolution
* Database Intro Locking and transactions::  Manage transactions, locking 
						and updating objects
@end menu

@c ============================================================================
@node Database Intro Classes, Database Intro Properties access, Database Introduction, Database Introduction
@comment  node-name,  next,  previous,  up
@subsection Database Classes Introduction

The Database Level is made of four classes: 

@table @code

@clindex EODatabase
@item EODatabase
It represents the database maintained by the SQL data server. It holds
the uniquing dictionary that maps primary keys to objects in memory and
the snapshots for all objects fetched from the data server outside any
transaction. A @code{EODatabase} object owns an @code{EOAdaptor} object
that is used to access the model for the database. @code{EODatabase}
objects can have several @code{EODatabaseContext} objects to manage
concurrent transaction scopes.

@clindex EODatabaseContext
@item EODatabaseContext
Controls a transaction scope with the SQL data server. It owns a
corresponding @code{EOAdaptorContext} and can have several
@code{EODatabaseChannel} objects to actually perform the operations with
the SQL data server. It also controls the locking strategy used to lock
objects in the data server, keeps uniquing and snapshot dictionaries
until the transaction is committed and handles nested transactions.

@clindex EODatabaseChannel
@item EODatabaseChannel
Used to actually perform fetch, insert, update, delete and lock
operations with the SQL data server. It owns a @code{EOAdaptorChannel}
object that is used to perform all the operations.

@clindex EOGenericRecord
@item EOGenericRecord
The generic Application Object class. It implements an object that
remembers its entity and keeps its properties as a @code{NSDictionary}.

@end table

@c ============================================================================
@node Database Intro Properties access, Mapping from rows to objects, Database Intro Classes, Database Introduction
@comment  node-name, next,  previous,  up
@subsection Uniform properties access

@cindex property access
@clindex EOKeyValueCoding

The Database Level uses objects from user defined classes to hold data
fetched as rows from the data server. These classes might have different
properties (attributes) accesible through accessor methods returning or
taking as argument different types, but the Database Level must be
able to access them both in writing and reading in an uniform manner.

Writing is necessary when the object is fetched or refetched from the
database and values in the row are to be tranfered to the object
(@pxref{Mapping from rows to objects}). Reading is needed when the
object is about to be inserted or updated into the data server, when its
properties must be assembled into a row (@code{NSDictionary} instance) used
in Adaptor Level operations.

Access to all the object properties is implemented in the
@code{EOKeyValueCoding} category of @code{NSObject}, which implemets the
access to the properties by name instead of accessor methods. 

@example
@@interface NSObject(EOKeyValueCoding)

-(BOOL)takeValuesFromDictionary:(NSDictionary*)dictionary
-(NSDictionary*)valuesForKeys:(NSArray*)keys

@@end
@end example

Setting properties is performed through @code{takeValuesFromDictionary:}.
This methods uses the keys in the @i{dictionary} argument to name the
properties and their corresponding values as the values to be set.

Getting values for properties from objects is done through
@code{valuesForKeys:} method. Its @i{keys} argument is an array of
properties names and its return value is a @code{NSDictionary} with the
the properties names as keys and their corresponding values taken from the
receiver as values.

Normally users will not want to implement these methods and will use the
default ones. Classes that implement these methods are @code{NSObject},
@code{NSDictionary} class cluster and @code{EOGenericRecord}.

@code{NSObject} implementation attempts to use existing accessor methods
or instance variables to access properties by name and performs a large
set of type conversions to and from standard @code{C} types and
@code{OpenStep} value objects (@code{NSString}, @code{NSNumber}).

To access the properties @code{valuesForKeys:} does the following for each
@i{key} in @i{keys} argument (example property name: @b{salary})

@quotation
@enumerate

@item If the receiver has a method `@i{key}' then that method is invoked
and its result (`@i{value}') is inserted in the returned dictionary under
the key `@i{key}' (example methods @code{-(id)salary}, @code{-(int)salary}).
If the method does not return an object type then type conversions are
made.

@item If the receiver has an instance variable named `@i{key}' then the
`@i{value}' contained in inserted in the returned dictionary under the key
`@i{key}' (example instance variable: @code{int salary}). If the instance
variable does not return an object type then type conversions are made.

@item If the receiver has no method or instance variable named `@i{key}'
then the returned dictionary will contain no key--value pair for the key
`@i{key}' (example: returned dictionary will have not @code{salary} key).

@end enumerate

@i{key} is expected to be @code{NSString}. If the method does not return
an object type then its result is converted to @code{NSString} for
@code{char*} and to @code{NSNumber} for other integer @code{C} types
(@code{char}, @code{unsigned char}, @code{short}, @code{unsigned short},
@code{int}, @code{unsigned int}, @code{long long}, @code{unsigned long
long}, @code{float}, @code{double}).

@end quotation

To set properties @code{takeValuesFromDictionary:} does the following for
each @i{key}--@i{value} pair in @i{dictionary} argument (example property
name @b{salary} with a value of @b{100}):

@quotation
@enumerate

@item If the receiver has a method `@code{set}@i{Key}@code{:}' then that
method is invoked and with the @i{value} as argument. For example for
@code{-(void)setSalary:(NSNumber*)} method definition 
@example 
[object setSalary:value]
@end example
is invoked, and for @code{-(void)setSalary:(int)} method definition
@example 
[object setSalary:[value intValue]]
@end example
is invoked.  If the method's argument is not an object type then the value
is converted to the appropriate type. 

@item If the receiver has an instance variable named `@i{key}' then it is
assigned the @i{value}. For example for @code{id salary} variable
definition
@example
[salary autorelease]; 
salary = [value retain]
@end example
is executed and for @code{int salary} variable definition 
@example
salary = [value intValue]
@end example
is executed. If the instance variable's type is not an object type then the
@i{value} is converted to the appropriate type. 

@item If the receiver has no `set@i{Key}' method or @i{key} instance
variable then the method does nothing.

@end enumerate

@i{key} is expected to be @code{NSString}. If the argument of
`@code{set}@i{Key}@code{:}' is not an object the value from the @i{value}
object is converted to the corresponding @code{C} type; for @code{char*}
the @i{value} is sent @code{stringValue} to convert it in @code{NSString}
then it uses @code{cString} and for (@code{char}, @code{unsigned char},
@code{short}, @code{unsigned short}, @code{int}, @code{unsigned int},
@code{long long}, @code{unsigned long long}, @code{float}, @code{double})
@i{value} is treated as a @code{NSNumber}. If an attempt is made to
convert @code{EONull} value to an @code{C} type then the object is sent
@code{unableToSetNullForKey:}@i{key} message.

@end quotation

@c ============================================================================
@node Mapping from rows to objects, Database Intro Uniquing, Database Intro Properties access, Database Introduction
@comment  node-name,  next,  previous,  up
@subsection Mapping from rows to objects

@cindex database, mapping rows to objects
@cindex mapping of rows

The main feature of the Database Level is to map rows fetched by the Adaptor
Level to Application Objects and to pack properties from the Application
Objects into rows for @code{INSERT} and @code{UPDATE} operations. The
mapping operations are performed by the @code{EODatabaseChannel} instances
as they fetch, insert or update objects. 

When inserting (updating), the database channnel uses the following algorithm:

@quotation
@enumerate

@item
Determine the entity for the application object (referred as object). If
the object responds to @code{entity} then the object is sent
@code{entity}. Else the model is sent @code{entityForClass:} with the
object's class as an argument.

@item
Send the object @code{valuesForKeys:} to get the values the channel must
insert (update). The properties names are the names of the class
properties attributes in the object's entity.

@item Perform adaptor @code{INSERT} (@code{UPDATE}) operation.

@end enumerate
@end quotation

When the database channel is fetching objects from a given entity (called
current entity) it performs the following steps: (@pxref{Database Features})

@quotation
@enumerate

@item
Use the @code{EOAdaptorChannel} to fetch a row (a @code{NSDictionary}
instance) from the data server.

@item Use the uniquing (@pxref{Database Intro Uniquing}) mechanism to determine
to which application object the values are to be transfered. If no object is
found then a new one is created, based on the class for the current entity. The
new object is initialized with @code{initWithPrimaryKey:entity:} if it responds
to this message else it is sent @code{init}.

@item Create fault objects for the object's relationships based on the values
in the fetched row (@pxref{Database Intro Relationships}).

@item Sends the object @code{takeValuesFromDictionary:} with a dictionary that 
contains the key--value pairs for class properties attributes and 
relationships.

@item Sends the object @code{awakeFromDatabaseChannel:} with @code{self} as an 
argument.

@end enumerate
@end quotation

@c ============================================================================
@node Database Intro Uniquing, Database Intro Relationships, Mapping from rows to objects, Database Introduction
@comment  node-name,  next,  previous,  up
@subsection Uniquing

@cindex database, uniquing
@cindex uniquing rows

In most applications it is required that no matter how many times a certain
row is fetched the data to be transfered in the same application object,
thus using less memory and keeping objects syncronized.

For example, in an application that lets the user edit person records the 
person inspector displays the department name. Suppose that there is  one
person inspector opened. To display the department name and location the
Control Level must get the department object for the person, so it fetches
the object for the department. If the user opens a department  inspector
for the same department, to edit the department location, the Control Level
fetches the same department again. If no uniquing is made there are two
objects for the same department. This brings the system in an inconsistent
state besides the fact that is uses more memory than necessary. With
uniquing, when the department is fetched again, the same object is
returned, so there is only one object corresponding to one row in the
database. 

For uniquing to be operational the library must be able to distinguish
among records from an entity (actually from a table in the data server).
This is accomplished by defining a @i{primary key} for the entity. The
primary key is a set of one or more attributes (usualy columns in the
entity's table) that identify rows in an unique way.

For example, for a @b{Person} entity, if persons are identified by a
person id, each person with a unique id, an @b{personId} attribute
corresponding to the @code{person_id} column in the @code{PERSONS} table
could be defined and set as the primary key attribute for the @b{Person}
entity.

When a row from an entity is fetched, its corresponding primary key is
computed by sending the entity
@example
[entity primaryKeyForRow:theRow]
@end example
message, which returns a @code{NSDictionary} containing the primary key
for that row (primary key attributes as keys and the corresponding values
from the @code{theRow}. 

Uniquing is controlled by the @code{EODatabase} and
@code{EODatabaseChannel} objects. The @code{EODatabase} maintains a
uniquing dictionary that has the entity and primary key pairs as keys and
their corresponding Application Objects as values. This dictionary does not
retain the Application Objects, so Application Objects must call the
@code{forgetObject:} from the @code{EODatabase} class when they get
deallocated. This gives the @code{EODatabase} objects a chance to remove
that object from the uniquing dictionary. If this dictionary is not
updated when the object is deallocated, the first time the object is
fetched, the system will find some object under that primary key and try
to set the values fetched into an deallocated object. 

During transactions, the @code{EODatabaseContext} keep a stack of
uniquing dictionaries for each nested transaction. When the transaction
is committed the uniquing information is folded in the parent
transaction uniquing dictionary on in the database context's
@code{EODatabase}.

By default the @code{EODatabase} uniques objects, but this behavior can
be controlled through
@example
-(void)setUniquesObjects:(BOOL)flag
@end example
and cannot be changed while the database has open channels.

When uniquing is in effect, while fetching, the @code{EODatabaseChannel}
after getting a row from the @code{EOAdaptorChannel}, computes the primary
key for that row and asks the database context and database for the object
for that primary key. If an object is already registered, values will be
set in that object, and if no object is registered the channel create one
(@pxref{Mapping from rows to objects}) and records it in its context
uniquing dictionary. 

@c ============================================================================
@node Database Intro Relationships, Database Intro Locking and transactions, Database Intro Uniquing, Database Introduction
@comment  node-name,  next,  previous,  up
@subsection Resolving relationships

@cindex database, resolve relationships
@cindex relationship resolution

Another key feature of the Database Level is the automatic relationship
resolving. Sometimes one or more attributes in one row form a primary
key for a record in some other entity (see the Model an the
Relationships chapter). If someone is working at the Adaptor Level he
has to fetch the objects described by the relationship explicitly. When
working at the Database Level when the @code{EODatabaseChannel} is
fetching an object from an entity it uses the Adaptor Level to fetch the
attributes the entity has, then it resolves the relationships defined
for that entity. The objects pointed by the relationships are added to
the dictionary with the object's properties and set in the object with
the @code{takeValuesFromDictionary:} method.

When resolving relationships the @code{EODatabaseChannel} does not fetch
the objects pointed by the relationship immediately. Instead of fetching
them immediately it creates some stand-in objects, called faults. These
faults behave like the real objects until they are sent a message that
they cannot handle, when they fetch the data from the database. When a
fault object is sent a message it cannot handle, it fetches the data it
represents and transforms the fault into the real object.

There are two kind of faults created by the library: to-one faults for
to-one relationships and to-many faults for to-many
relationships. To-many faults represent @code{NSArray} objects, and are
described by the destination entity and the qualifier they will use to
fetch. To-one faults can represent any class that is used for
Application Objects and are described by the destination entity and the
primary key for the object. To-one faults are handled in a special way
regarding to uniquing. As to-one faults represent objects they are
registered in the uniquing dictionary under the primary key for the
entity; before attempting to create a to-one fault the
@code{EODatabaseChannel} looks up in its @code{EODatabaseContext} and
@code{EODatabase} for an object from the destination entity with the
same primary key and if one is found it uses that object instead of
creating a fault (@pxref{Database Intro Uniquing}).

Relationships are not fetched immediately for two reasons. First the
channel that performs the fetch is busy fetching so it cannot handle
another fetch. Second, with the delayed fetching the application is
speeded up because it will fetch the objects as it needs them, not all
at once.

The relationship resolution mechanism has one disadvantage because of
the retain--release mechanism in the Foundation Library. If
relationships are defined so that retain cycles appear (a person has a
to-one relationship to his boss and the boss has to-many relationship to
his employees) and objects never get deallocated. To overcome this
problem the library uses a Garbage Collector (see Garbage Collector).

Users can create faults themselves using @code{EOFault} class
methods. When faulting a to-one fault, if the entity and primary key do
not describe one and only one object an
@code{EOUnableToFaultToOneException} exception is raised.

@c ============================================================================
@node Database Intro Locking and transactions,  , Database Intro Relationships, Database Introduction
@comment  node-name,  next,  previous,  up
@subsection Transactions, locking and updating objects

@cindex database, transaction
@cindex database, locking
@cindex database, updates

One of the most difficult to understand and to work with chapter in
databases are transactions and record locking for updates. Transactions
are used in database operations to specify a set of operation that will
either succeed all of them of fail all even if only one cannot be
executed. This is needed to insure database integrity, i.e. not to leave
the database in an inconsistent state if one operation fails. Locking is
needed to handle concurrent access to the database maintained by the
data server. For example if one user is about to update a record he must
lock that record first then perform the update; the record will be
eventually unlocked when the transaction it was lock in is committed or
aborted. If the user does not lock the record, a second user might
update that record in between. The first user is not notified in any way
that the record he is about to update has just been updated by someone
else. If the secod user attemps to update the record locked by someone
else the data server issues an error and the record is not updated.

An example can be automatic key generation. Say the table @b{KEYS} has
two columns, @b{name} and @b{maxkey}, first representing a product name
and the other the current unassigned serial number for that
product. Whenever a product is added into the database we want to assign
it a unique serial number so we must get the current unassigned serial
number and then increment it.
@example
BEGIN TRANSACTION
SELECT maxkey 
    FROM KEYS HOLDLOCK 
    WHERE name = 'product name';
UPDATE TABLE KEYS 
    SET maxkey = maxkey + 1
    WHERE name = 'product name';
COMMIT TRANSACTION
@end example
To lock the record in the data server between the @code{SELECT} and the
@code{UPDATE} operation the @code{HOLDLOCK} clause is used.

To lock an object (or its corresponding record into the database)
outside any transaction the users must buid their own locking server,
perhaps using the distributed objects mechanism built into the
Foundation Library.

The Database Level offers some fetures to automatically handle and
control locking and update operations in transactions and outside
them. The @code{EODatabaseContext} defines the locking strategy to be
used in update operations, for all updates performed by the context's
channels. It also remembers objects explicitly locked during a
transaction with the @code{EODatabaseChannel} @code{lockObject:} method.

The locking strategies used for updates are:

@table @b

@item EOUpdateWithPessimisticLocking
The @code{EODatabaseChannel} will require that an object be locked in
the current transaction for an update to procedd. If the object given to
@code{updateObject:} is not registered as locked in the channel's
context the channel uses the @b{EOUpdateWithOptimisticLocking} strategy.

@item EOUpdateWithOptimisticLocking
Uses snapshots (last known state of the database record) for rows to
check that the record has not changed since it was last fetched. If the
values in the snapshot differ from those in the database or there is no
snapshot registered in the channel's context or database the operation
fails.

@item EOUpdateWithNoLocking
The @code{EODatabaseChannel} will blindly perform update
operations. Objects need not be locked into the database and snapshots
are not used in update operations to check that the recoed was not
modified.

@item EONoUpdate
Under this strategy the context's chanels will fail on
@code{updateObject:}. This strategy, combined with snapshotting turned
off in the context's @code{EODatabase} may be used to consult databases
in a read only fashion without snapshotting overhead.

@end table

Snapshots are the last known values for attributes from a row. In the
model for a database, users can define attributes used for locking,
i.e. attributes whose values will be kept in snapshots. Snapshots are
recorded in the @code{EODatabaseContext} while in a transaction when
objects are fetched or inserted and are transfered in the context's
database then the top level transaction is committed. The
@code{EODatabase} can be configured wether to keep snapshots between
transactions or not.

Keeping snapshots between transactions has the advantage that an object
fetched in a transaction already committed need not be refetched to make
other snapshots.


@c ============================================================================
@node Database Features, Database Using, Database Introduction, The database level
@comment  node-name,  next,  previous,  up
@section Database Features

@menu
@end menu

@c ============================================================================
@node Database Using,  , Database Features, The database level
@comment  node-name,  next,  previous,  up
@section Database Using

@menu
@end menu

1. Insert from a plist to make a database
2. Automatic primary key generation
3. Operations:
	insert person
	remove person
	insert project
	remove project
	add person to a project
	remove person from project
4. Fetching
	adaptor fetch of person and thier projects (with two channels)
	database fetch of persons and their properties
	using a non-class property relationship to get the persons for a prj
	fetch order
5. Update 
	person's record
	project's record


@c =========================================================================
@c =========================================================================
@node Writing a new adaptor, The complete model, The database level, Top
@comment node-name, next, previous, up
@chapter Writing a New Adaptor

GDL comes with written adaptors for Sybase, Microsoft SQL Server and
PostgreSQL databases. Other database servers can be supported as well if
adaptors are written for them. You should read this chapter if you
intend to write a new adaptor.

To create a new adaptor you usually need to implement some concrete
subclasses of @code{EOAdaptor}, @code{EOAdaptorContext} and
@code{EOAdaptorChannel}. If the SQL language understood by the database
server you will also have to subclass @code{EOSQLExpression}.

In the rest of this chapter are presented the methods that you usually
need to implement in the adaptor subclasses and a description of
@code{EOSQLExpression}.

@menu
* EOAdaptor::                   
* EOAdaptorContext::            
* EOAdaptorChannel::            
* EOSQLExpression::             
@end menu

@c =========================================================================
@node EOAdaptor, EOAdaptorContext, Writing a new adaptor, Writing a new adaptor
@comment node-name, next, previous, up
@section EOAdaptor

@clindex EOAdaptor

You usually have to implement the following methods of @code{EOAdaptor}:

@table @asis

@item - (Class)@b{expressionClass}

the SQL expression class used to generate the database operations (default is @code{EOSQLExpression})

@item - (Class)@b{adaptorContextClass}

the adaptor context class (default is @code{EOAdaptorContext})

@item - (Class)@b{adaptorChannelClass}

the adaptor channel class (default is @code{EOAdaptorChannel})

@item - @b{formatAttribute:}(EOAttribute*)@i{attribute}

returns an @code{EOExpression} object that can be used as a table name in SQL expressions. The default implementations sends the @code{expressionValueForContext:} message to @i{attribute}.

@item - @b{formatValue:}@i{value} @b{forAttribute:}(EOAttribute*)@i{attribute}

returns a value that can be used in SQL expressions. The adaptor should perform any additional character escaping needed the database server. The default implementation sends to @i{value} the @code{expressionValueForContext:} message. You should not make this formatting by writing categories to classes, because if one uses several adaptors at the same time the methods conversion methods will be overwritten each other.

@item - (BOOL)@b{isValidQualifierType:}(NSString*)@i{typeName}

returns @code{YES} if values of type @i{typeName} can be used in qualifiers

@end table

The @code{EOAdaptor} class also maintains the model and the connection dictionary. A new adaptor should decide what are the information needed to create a new database connection and require them to be specified in the connection dictionary.

@c =========================================================================
@node EOAdaptorContext, EOAdaptorChannel, EOAdaptor, Writing a new adaptor
@comment node-name, next, previous, up
@section EOAdaptorContext

@clindex EOAdaptorContext

The @code{EOAdaptorContext} represents a transaction scope within database server. An important issue you have to take into consideration is whether several channels can be opened or not within the same transaction. Some database servers such as Sybase allow only one channel for example. If this is the case with your server you have to verify the programmer does not create more than one channel per context.

The methods you have to implement are those that begin, commit and rollback a transaction since these methods in @code{EOAdaptorContext} simply return @code{NO}.

@table @asis

@item - (BOOL)@b{primaryBeginTransaction}

opens a new transaction and returns @code{YES} if the action was successful

@item - (BOOL)@b{primaryCommitTransaction}

commits the transaction that is currently opened and returns @code{YES} if the action was successful

@item - (BOOL)@b{primaryRollbackTransaction}

rollbacks the transaction that is currently opened and returns @code{YES} if the action was successful

@end table

These are the so called ``primary'' methods because they do only the basic operations and do not take any actions, by calling the delegate for example, when the operation succeed or failed. Of course you can implement in your subclass the top methods but then you have to implement the whole behavior they have.

Another important method is

@table @asis

@item - (BOOL)@b{canNestTransactions}

@end table

that should return @code{YES} if transactions can be nested.

@c =========================================================================
@node EOAdaptorChannel, EOSQLExpression, EOAdaptorContext, Writing a new adaptor
@comment node-name, next, previous, up
@section EOAdaptorChannel

Subclassing the @code{EOAdaptorChannel} is the most difficult part in writing a new adaptor. This class contains almost the all code dependent on database server. The database client library can simplify a lot this task if it provides all the information you need.

The things you have to know before you start to write any line of code are the following:

@itemize @bullet

@item what are the types supported by the database and how do they map to Objective-C classes. The GDL existing adaptors use categories to the usual Foundation classes to create the object values or obtain the database value from an object.

@item how to retrieve a value of a given type after the fetch request was made. If all the types are supported in a uniform manner, e.g. there is only one way to access all the values no matter what is their type, then the task is simplified. Some database client libraries for example make a distinction between elementary types (such as characters, integers and floats) and large data (also known as BLOB or binary data).

@item how to evaluate an arbitrary SQL expression (using @b{evaluateExpression:}) that could possibly contain more than one request. Such an evaluation implies that you should be able to find out of what kind were the requests from the original expression.

@item if an arbitrary fetch request was evaluated using @b{evaluateExpression:} the library has to tell what were the attributes involved in request.

@item you have to be able to find out what are the tables from the database the adaptor is connected to. For each table you also have to find out what are the columns and their types.

@end itemize

The methods you have to override in your concrete subclass of @code{EOAdaptorChannel} are:

@table @asis

@item - (NSMutableDictionary*)@b{primaryFetchAttributes:}(NSArray*)@i{attributes}
@itemx @b{ withZone:}(NSZone*)@i{zone}

Fetch the attributes specified in the @i{attributes} array that contains the @code{EOAttribute} objects. The method should return a dictionary having as key the name of the attribute (not the attribute itself) and as value an object whose class is specified in the attribute and whose value was retrieved from the database. The objects should be allocated from @i{zone}. This methods advances to the next record retrieved. If no more records follow this method should return @code{nil} otherwise the dictionary row should be returned.

@item - (BOOL)@b{evaluateExpression:}(NSString*)@i{anExpression}

Evaluates the arbitrary SQL expression specified by @i{anExpression} and returns @code{YES} if the evaluation succeeds or @code{NO} otherwise.

@item - (NSArray*)@b{describeResults}

Returns an array of @code{EOAttribute}s corresponding to the last fetch operation sent to the database. The attributes returned should not necessary exist in the model. Each attribute should have at least a name and the external type specified.

The result is undefined if the last request was not fetch request.

@item - (EOModel*)@b{describeModelWithTableNames:}(NSArray*)@i{tableNames}

@itemx - (NSArray*)@b{describeTableNames}

@itemx - (BOOL)@b{readTypesForEntity:}(EOEntity*)@i{anEntity}

@itemx - (BOOL)@b{readTypeForAttribute:}(EOAttribute*)@i{anAttribute}

These methods are used to determine a model from the meta-information stored by the database. If these information is not available you can not implement these methods.

@end table

You may also need to implement the following methods if the database client library does handle differently the database types:

@table @asis

@item - (BOOL)@b{insertRow:}(NSDictionary*)@i{aRow} @b{forEntity:}(EOEntity*)@i{anEntity}

@item - (BOOL)@b{updateRow:}(NSDictionary*)@i{aRow}
@itemx  @b{ describedByQualifier:}(EOQualifier*)@i{aQualifier}

@item - (BOOL)@b{deleteRowsDescribedByQualifier:}(EOQualifier*)@i{aQualifier}

@end table

Special care should be taken in implementing these methods; they should return @code{NO} if no record was affected by the operation, so if the database client library does not provide you this information you have to execute a fetch operation before to find out the number of affected rows.


@c =========================================================================
@node EOSQLExpression,  , EOAdaptorChannel, Writing a new adaptor
@comment node-name, next, previous, up
@section EOSQLExpression

@clindex EOSQLExpression
@clindex EOSelectSQLExpression
@clindex EOUpdateSQLExpression
@clindex EOInsertSQLExpression
@clindex EODeleteSQLExpression

If the SQL language understood by your database server has some small variations to the SQL language generated by GDL, you may also need to write a subclass of @code{EOSQLExpression}, the class that is responsible with the SQL operation generation. Usually you need to do this to support locks in SELECT operations.

@code{EOSQLExpression} has four subclasses that are used for SQL generation:

@itemize @bullet

@item @code{EOSelectSQLExpression}

@item @code{EOUpdateSQLExpression}

@item @code{EOInsertSQLExpression}

@item @code{EODeleteSQLExpression}

@end itemize

The @code{EOSQLExpression} class has four methods that return the subclasses used to generate an expression:

@itemize @bullet

@item + (Class)@b{selectExpressionClass}

@item + (Class)@b{insertExpressionClass}

@item + (Class)@b{deleteExpressionClass}

@item + (Class)@b{updateExpressionClass}

@end itemize

To customize a particular SQL operation you have to follow these steps:

@itemize @bullet

@item create a subclass of @code{EOSQLExpression}, lets say it @code{EOCustomSQLExpression}

@item create a subclass of the class corresponding to the operation you want. For example if you want to modify the @code{SELECT} operation then you have to subclass from @code{EOSelectSQLExpression}. Let's name this class @code{EOCustomSelectExpression}.

@item implement the @code{selectExpressionClass} method of @code{EOCustomSQLExpression} to return the @code{EOCustomSelectExpression}.

@item implement the method you need to the @code{EOCustomSelectExpression} class.

@item implement the @code{expressionClass} method to your custom @code{EOAdaptor} class to return the @code{EOCustomSQLExpression}.

@end itemize

This way your adaptor classes will use your custom @code{EOSQLExpression} to generate SQL expressions.


@c =========================================================================
@c =========================================================================
@node The complete model, Concept Index, Writing a new adaptor, Top
@comment node-name, next, previous, up
@appendix The Complete Example Model

@example
@{
  EOModelVersion = 1;
  adaptorName = Sybase;
  adaptorClassName = SybaseAdaptor;
  connectionDictionary = @{
    databaseName = test;
    userName = sa;
    password = "";
  @};
  entities = (
    @{
      attributes = (
        @{
          columnName = first_name;
          externalType = varchar;
          name = firstName;
          valueClassName = NSString;
        @},
        @{
          columnName = last_name;
          externalType = varchar;
          name = lastName;
          valueClassName = NSString;
        @},
        @{
          columnName = person_id;
          externalType = int;
          name = personId;
          valueClassName = NSNumber;
          valueType = i;
        @},
        @{
          columnName = dept_id;
          externalType = int;
          name = deptId;
          valueClassName = NSNumber;
          valueType = i;
        @},
        @{
          columnName = boss_id;
          externalType = int;
          name = bossId;
          valueClassName = NSNumber;
          valueType = i;
        @}
      );
      attributesUsedForLocking = (personId, firstName, lastName);
      classProperties = (personId, firstName, lastName);
      externalName = PERSON;
      name = Person;
      primaryKeyAttributes = (personId);
      relationships = (
        @{
          destination = Department;
          isToMany = N;
          joins = (
            @{
              destinationAttribute = deptId;
              joinOperator = EOJoinEqualTo;
              joinSemantic = EOInnerJoin;
              sourceAttribute = deptId;
            @}
          );
          name = toDepartment;
        @},
        @{
          destination = Person;
          isToMany = N;
          joins = (
            @{
              destinationAttribute = personId;
              joinOperator = EOJoinEqualTo;
              joinSemantic = EOInnerJoin;
              sourceAttribute = bossId;
            @}
          );
          name = toBoss;
        @},
        @{
          destination = PersonProject;
          isToMany = Y;
          joins = (
            @{
              destinationAttribute = personId;
              joinOperator = EOJoinEqualTo;
              joinSemantic = EOInnerJoin;
              sourceAttribute = personId;
            @}
          );
          name = toPersonProject;
        @},
        @{
          definition = toDepartment.toFacility;
          name = toFacility;
        @}
      );
    @},
    @{
      attributes = (
        @{
          columnName = name;
          externalType = varchar;
          name = name;
          valueClassName = NSString;
        @},
        @{
          columnName = dept_id;
          externalType = int;
          name = deptId;
          valueClassName = NSNumber;
          valueType = i;
        @},
        @{
          columnName = facility_id;
          externalType = int;
          name = facilityId;
          valueClassName = NSNumber;
          valueType = i;
        @}
      );
      attributesUsedForLocking = (deptId, name, facility_id);
      classProperties = (name, deptId);
      externalName = DEPARTMENT;
      name = Department;
      primaryKeyAttributes = (deptId);
      relationships = (
        @{
          destination = Facility;
          isToMany = N;
          joins = (
            @{
              destinationAttribute = facilityId;
              joinOperator = EOJoinEqualTo;
              joinSemantic = EOInnerJoin;
              sourceAttribute = facilityId;
            @}
          );
          name = toFacility;
        @}
      );
    @},
    @{
      attributes = (
        @{
          columnName = name;
          externalType = varchar;
          name = name;
          valueClassName = NSString;
        @},
        @{
          columnName = facility_id;
          externalType = int;
          name = facilityId;
          valueClassName = NSNumber;
          valueType = i;
        @}
      );
      attributesUsedForLocking = (facilityId);
      classProperties = (name, facilityId);
      externalName = FACILITY;
      primaryKeyAttributes = (facilityId);
      name = Facility;
    @},
    @{
      attributes = (
        @{
          columnName = person_id;
          externalType = int;
          name = personId;
          valueClassName = NSNumber;
          valueType = i;
        @},
        @{
          columnName = project_id;
          externalType = int;
          name = projectId;
          valueClassName = NSNumber;
          valueType = i;
        @}
      );
      attributesUsedForLocking = (personId, projectId);
      classProperties = (personId, projectId);
      externalName = PERSON_PROJECT;
      name = PersonProject;
      primaryKeyAttributes = (personId, projectId);
      relationships = (
        @{
          destination = Person;
          isToMany = Y;
          joins = (
            @{
              destinationAttribute = personId;
              joinOperator = EOJoinEqualTo;
              joinSemantic = EOInnerJoin;
              sourceAttribute = personId;
            @}
          );
          name = toPerson;
        @},
        @{
          destination = Project;
          isToMany = Y;
          joins = (
            @{
              destinationAttribute = projectId;
              joinOperator = EOJoinEqualTo;
              joinSemantic = EOInnerJoin;
              sourceAttribute = projectId;
            @}
          );
          name = toProject;
        @}
      );
    @},
    @{
      attributes = (
        @{
          columnName = name;
          externalType = varchar;
          name = name;
          valueClassName = NSString;
        @},
        @{
          columnName = project_id;
          externalType = int;
          name = projectId;
          valueClassName = NSNumber;
          valueType = i;
        @}
      );
      attributesUsedForLocking = (name, projectId);
      classProperties = (name, projectId);
      externalName = PROJECT;
      name = Project;
      primaryKeyAttributes = (name, projectId);
      relationships = (
        @{
          destination = PersonProject;
          isToMany = Y;
          joins = (
            @{
              destinationAttribute = projectId;
              joinOperator = EOJoinEqualTo;
              joinSemantic = EOInnerJoin;
              sourceAttribute = projectId;
            @}
          );
          name = toPersonProject;
        @}
      );
    @}
  );
@}
@end example


@c =========================================================================
@c =========================================================================
@node Concept Index, Classes Index, The complete model, Top
@comment node-name, next, previous, up
@unnumbered Concept Index

@printindex cp


@c =========================================================================
@c =========================================================================
@node Classes Index,  , Concept Index, Top
@comment  node-name,  next,  previous,  up
@unnumbered Classes Index

@printindex cl

@c =========================================================================
@c Generate Short Contents
@c =========================================================================
@shortcontents

@c =========================================================================
@c Generate Complete Contents
@c =========================================================================
@contents

@c =========================================================================
@c Generate Complete Contents
@c =========================================================================
@unnumbered @emph{Preface}

@section About NET-Community

NET-Community was founded in 1995 with the purpose of developing and
supporting free software for the Internet and business community.  We
believe that in the long-term free software will provide individuals
and businesses with the most flexible and open solutions for their
needs; while expensive proprietary solutions will be slowly phased
out.  Companies will choose free software because it offers greater
flexibility, lower maintenance costs, and more responsive changes to
market demands than closed proprietary systems.  With free software,
companies immediately gain the advantage of combined development by
all vendors supporting the software; most proprietary systems are
maintained by a single vendor and as such cannot keep pace with the
changes occuring in the marketplace.

By free software, we are referring to freedom not to its price.
Software freedom implies that users have the right to copy,
distribute, and modify the software for their own needs and that they
cannot deny other these rights.  Software freedom is healthy for the
software industry because it encourages open standards allowing those
consumers to choose vendors based upon their service, support, and
their committment to new software development.  With free software,
consumers are not stuck with a single vendor's proprietary system;
they can easily switch vendors if they are not happy with the service
they are getting.

With NET-Community providing your software support needs, you will have
the service and support to meet your business software needs.
NET-Community has extensive experience with the GNUstep Database Library
because we are directly involved in the design, development,
implementation, and testing of it.  We maintain direct contact with the
authors so that you have access to the most qualified support personnel.

NET-Community is happy to provide the GNUstep Database Library to the
Internet and business community.  We hope that you will find this
software useful, and that free software truly offers a professional,
quality alternative to proprietary software.

@section Acknowledgements

Thanks to Mircea Oancea and Ovidiu Predescu, the authors of the GNUstep
Database Library, for their commitment and hard work to make this
software a reality.  Thanks to all of the supporters and contributors of
NET-Community who help make sure that GNUstep software continues to be
developed and continues to be free.

Sincerely,@*
Scott Christley@*
President@*
NET-Community@*
@emph{"Providing free software for the global community."}

@bye
