Added commands and API sketch
[dbsrgits/dbic-future.git] / lib / DBIx / Class / Manual / Specification.pm
CommitLineData
7848cf7a 1=head1 NAME
2
3DBIx::Class::Manual::Specification
4
5=head1 SYNOPSIS
6
7This discusses the specification for DBIx::Class v0.09. Along with discussing
8new features, it will also include proper specification for features that exist
9in the DBIx::Class 0.08 versions that will be supported in DBIx::Class 0.09.
10Where appropriate, it will also discuss specifications for Data::Query and any
11other modules/distributions.
12
13=head1 MOTIVATIONS
14
15DBIx::Class has become one of, if not the, premier ORMs in the Perl community.
16However, its featureset has grown organically. As such, some features that were
17considered a good idea at one time proved to be implemented in such a way that
18prevented proper implementation of other features down the road. Examples
19include prefetching and searching.
20
21This document means to provide a solid foundation for future development so as
22to prevent painting the distribution into a corner for features that have not
23been conceived of at this time.
24
25=head1 GOALS
26
27This specification will be driven by the following design goals.
28
29=head2 Database-agnostic usage
30
31One of the biggest selling points of an ORM is that a programmer should be able
32to change the relational database used to back a given application without
33having to change anything but configuration. And, to a point, this works
34relatively well. Until it doesn't. DBIx::Class 0.09 will change that.
35
36=head2 Database-specific optimization
37
38As it turns out, the drive to be database-agnostic, makes it very hard to
39optimize for a given specific database's strengths. In order to support as many
40databases, the SQL generated generally ends up being at the lowest common
41denominator. This gives ORMs a bad name where performance is concerned. But, it
42doesn't have to be that way and DBIx::Class 0.09 will demonstrate how.
43
44=head2 Datastore-agnostic usage
45
46Data doesn't just live in relational databases anymore. There are many reasons,
47for this, the primary one being that the relational model doesn't necessarily
48reflect the structure of certain data models. But, there are many times when
49relational calculus represents the proper way of manipulating that data. Or,
50more commonly, a given relational query needs to merge data from relational and
51non-relational sources. DBIx::Class, along with Data::Query, will provide a
52single API for manipulating data in a relational fashion, regardless of whether
53that manipulation is in a datastore, within Perl, or both.
54
55=head2 Intuitive API
56
57Every API has unavoidable gribbly bits. This falls out of the fact that the
58problemspace a given API solves can never be fully mapped to it (an extension
59of Godel's Incompleteness Theorem). However, like Perl itself, the API should be
60organized and optimized so that the user only needs to know a minimum of the
61API's functionality in order to accomplish the most common tasks. Furthermore,
62that minimum should be easily discoverable in simple synopses and examples.
63
64=head2 Extensible API and backend
65
66Without breaking or, in as many cases as possible I<knowing>, existing backend
67implementation details, the functionality of DBIx::Class should be extensible.
68Both the API (new contact points) and backend (new datastores, etc) should be
69extended knowing a simple API for doing so. This implies that as many pieces as
70possible of the backend functionality should be overridable separate from every
71other piece.
72
73=head1 RESTRICTIONS
74
75Fill this part in.
76
77=head1 RELATIONAL THEORY
78
79(B<Author's note:> To understand the fundamental underpinnings of DBIx::Class
800.09's choice of features, it is necessary to have a common understanding of
81relational theory. I recommend that everyone at least read this section once in
82order to be familiar with the terms I use throughout this document.)
83
84Relational theory (calculus or algebra - the difference is esoteric) is, at its
85roots, all about set theory and set manipulations. Each row in a table (or
86tuple) is an element of a set. The various clause (or operations) in a SQL
87statement can be viewed as set manipulators that take one or more sets of tuples
88as input and provide a set of tuples as output.
89
90A SQL statement has many clauses and they are evaluated in a very specific order
91that is different from the order they are presented. (As mutations share all of
92their clauses with queries and evaluate in the same order, only queries will be
93discussed here.) The order of evaluation for a SELECT statement is:
94
95=over 4
96
97=item * FROM (with JOINs evaluated in left-to-right order)
98
99=item * WHERE (with AND/OR evaluated in left-to-right order within each
100parenthetical block)
101
102=item * GROUP BY
103
104=item * SELECT
105
106=item * HAVING
107
108=item * ORDER BY
109
110=back
111
112(Expand here.)
113
114=head1 FEATURES
115
116=head2 Basic Features
117
118An ORM must provide some very basic features. They are, in essence, the ability
119to:
120
121=over 4
122
123=item * Retrieve data from a relational database (a.k.a., select)
124
125=item * Insert, update, and delete in that relational database (a.k.a., mutate)
126
127=back
128
129These functions are generally achieved by providing some API to the SELECT
130statement that returns a collection of objects. These objects then allow for
131updating and deleting. The same API that allows for SELECT also, generally, will
132allow for creation and, possibly, deletion. Most ORMs do this modelling by
133mapping a class to a table and an instance of that class to a given row in that
134table.
135
8b8bab95 136DBIx::Class takes a different approach entirely. Instead of treating the row as
137the atomic unit, DBIx::Class 09 will treat the column as the atomic unit. This
138opens up several possibilities:
7848cf7a 139
8b8bab95 140=over 4
7848cf7a 141
8b8bab95 142=item * The definition of a table fall out naturally as a collection of columns
143
144=item * Defining custom searches is a matter of creating a collection of columns on the fly.
145
146=item * Validating values is easily handled regardless of where the column is used.
147
148=item * Enumeration tables can be hidden behind a column definition, allowing optimization to ENUM as appropriate.
149
150=back
7848cf7a 151
152=head3 Sources
153
154A source, at its simplest, is the representation of a single table in a
155relational database. For example, the table `artists`. But, a source can be
156much more than that. Within a relational database, "`artists JOIN cds`" forms a
157source containing the columns of both `artists` and `cds`. Taken to the logical
158extreme, the FROM clause of a query forms a single source. A subquery can also
159be viewed as a source. (In fact, any table or join can be viewed as the subquery
160"(SELECT * FROM table) AS table".)
161
8b8bab95 162Under the hood, a source acts as a collection of column definitions. When a
163source feeds into
164
165=head3 Resultsets (RENAME ME)
7848cf7a 166
167The resultset is arguably the single most important breakthrough in DBIx::Class.
168It allows for the gradual building of a SQL statement and reuse of that building
169for more than just SELECT statements. In addition to being able to separate
170responsibilites by letting different pieces of an application (such as security)
171decorate the resultset appropriately, a resultset can also be reused for various
172needs. The same resultset can be used for a query, a mass update, a mass delete,
173or anything else.
174
175Under the hood, a resultset has a representation for each SQL clause. Each usage
176of the resultset will take the clauses that make sense for that usage and leave
177the others.
178
179(Expand here, detailing each usage of a resultset and the clauses that each
180uses.)
181
8b8bab95 182=head3 Objects (aka, Rows)
7848cf7a 183
8b8bab95 184Traditionally, there is row object is acts as a hashref representing a row in a
185table. This representation is simple to implement, meets the 80/20 case, and is
186completely wrong. It fails when dealing with GROUP BY clauses, custom queries,
187and is generally inflexible.
7848cf7a 188
8b8bab95 189DBIx::Class 09 chooses instead to model a row as an object that is a collection
190of columns that contain values. This means that the object is defined by the
191resultset that generates the stream the object comes from. In the standard case,
192the resultset's store is a single table and all columns are selected, acting the
193same way as a DBIx::Class 08 row object would.
7848cf7a 194
195=head2 Queries as streams
196
197A grouping of data can be viewed as either a collection or a stream. The main
198difference is that a collection is eager and a stream is lazy. For large
199datasets, collections can be very expensive in terms of memory and time (filling
200that memory). Streams, on the other hand, defer loading anything into memory
201until the last possible moment, but are easily convertible into a collection as
202needed. (q.v. Higher Order Perl for more information.)
203
8b8bab95 204=head1 EXAMPLES
7848cf7a 205
9a8fc0f9 206 subtype Year as Num where { $_ > 0 && $_ <= 9999 };
207
208 table Artist {
209 column artist_id => ( isa => 'Num', auto_increment => 1, primary_key => 1 );
210 column name => ( isa => 'String', max_length => 50, nullable => 0 );
211 column rank => ( isa => 'Num', default => 13 );
212
213 has_many 'CD';
214
215 table 'artists';
216 }
217
218 table CD {
219 column cdid => ( isa => 'Num', auto_increment => 1, primary_key => 1 );
220 column artist => ( isa => 'Num' );
221 column title => ( isa => 'String', max_length => 100 );
222 column year => ( isa => 'Year' );
223
224 belongs_to 'Artist';
225
226 table 'cds';
227 }
228
229 # The following four searches are equivalent:
230 my @artists = $schema->table('Artist')->search({
231 name => 'Bon Jovi',
232 })->all;
233
234 my @artists = $schema->search({
235 name => 'Bon Jovi',
236 }, {
237 from => 'Artist',
238 });
239
240 # If a class and table name would conflict and they don't refer to the same
241 # thing, a compile-time error is thrown.
242 my @artists = $schema->search({
243 'Artist.name' => 'Bon Jovi',
244 });
245
246 my @artists = $schema->search({
247 'artists.name' => 'Bon Jovi',
248 });
249
250 # The following searches are equivalent. Results will contain objects that
251 # respond to artist_name(), cd_name(), and year() and nothing else.
252 my @results = $schema->search({
253 'Artist.name' => [ 'Bon Jovi', 'Metallica' ],
254 'CD.year' => [ '2004', '2006' ],
255 }, {
256 select => [
257 [ 'Artist.name' => 'artist_name' ],
258 [ 'CD.name' => 'cd_name' ],
259 'CD.year',
260 ],
261 });
262
263 # Artist is the default table here.
264 my @results = $schema->table('Artist')->search({
265 'name' => [ 'Bon Jovi', 'Metallica' ],
266 'CD.year' => [ '2004', '2006' ],
267 }, {
268 select => [
269 [ 'name' => 'artist_name' ],
270 [ 'CD.name' => 'cd_name' ],
271 'CD.year',
272 ],
273 });
274
275 # CD is the default table here.
276 my @results = $schema->table('CD')->search({
277 'Artist.name' => [ 'Bon Jovi', 'Metallica' ],
278 'year' => [ '2004', '2006' ],
279 }, {
280 select => [
281 [ 'Artist.name' => 'artist_name' ],
282 [ 'name' => 'cd_name' ],
283 'year',
284 ],
285 });
286
287 # Note that joins are intuited through the existence of the relationships.
288
7848cf7a 289=head1 TODO
290
291=over 4
292
293=item * L</RESTRICTIONS> section needs to be filled in.
294
295=back
296
297=head1 AUTHOR(S)
298
299robkinyon: Rob Kinyon C<< <rkinyon@cpan.org> >>
300
301=head1 LICENSE
302
303You may distribute this code under the same terms as Perl itself.
304
305=cut