Commit | Line | Data |
7848cf7a |
1 | =head1 NAME |
2 | |
3 | DBIx::Class::Manual::Specification |
4 | |
5 | =head1 SYNOPSIS |
6 | |
7 | This discusses the specification for DBIx::Class v0.09. Along with discussing |
8 | new features, it will also include proper specification for features that exist |
9 | in the DBIx::Class 0.08 versions that will be supported in DBIx::Class 0.09. |
10 | Where appropriate, it will also discuss specifications for Data::Query and any |
11 | other modules/distributions. |
12 | |
13 | =head1 MOTIVATIONS |
14 | |
15 | DBIx::Class has become one of, if not the, premier ORMs in the Perl community. |
16 | However, its featureset has grown organically. As such, some features that were |
17 | considered a good idea at one time proved to be implemented in such a way that |
18 | prevented proper implementation of other features down the road. Examples |
19 | include prefetching and searching. |
20 | |
21 | This document means to provide a solid foundation for future development so as |
22 | to prevent painting the distribution into a corner for features that have not |
23 | been conceived of at this time. |
24 | |
25 | =head1 GOALS |
26 | |
27 | This specification will be driven by the following design goals. |
28 | |
29 | =head2 Database-agnostic usage |
30 | |
31 | One of the biggest selling points of an ORM is that a programmer should be able |
32 | to change the relational database used to back a given application without |
33 | having to change anything but configuration. And, to a point, this works |
34 | relatively well. Until it doesn't. DBIx::Class 0.09 will change that. |
35 | |
36 | =head2 Database-specific optimization |
37 | |
38 | As it turns out, the drive to be database-agnostic, makes it very hard to |
39 | optimize for a given specific database's strengths. In order to support as many |
40 | databases, the SQL generated generally ends up being at the lowest common |
41 | denominator. This gives ORMs a bad name where performance is concerned. But, it |
42 | doesn't have to be that way and DBIx::Class 0.09 will demonstrate how. |
43 | |
44 | =head2 Datastore-agnostic usage |
45 | |
46 | Data doesn't just live in relational databases anymore. There are many reasons, |
47 | for this, the primary one being that the relational model doesn't necessarily |
48 | reflect the structure of certain data models. But, there are many times when |
49 | relational calculus represents the proper way of manipulating that data. Or, |
50 | more commonly, a given relational query needs to merge data from relational and |
51 | non-relational sources. DBIx::Class, along with Data::Query, will provide a |
52 | single API for manipulating data in a relational fashion, regardless of whether |
53 | that manipulation is in a datastore, within Perl, or both. |
54 | |
55 | =head2 Intuitive API |
56 | |
57 | Every API has unavoidable gribbly bits. This falls out of the fact that the |
58 | problemspace a given API solves can never be fully mapped to it (an extension |
59 | of Godel's Incompleteness Theorem). However, like Perl itself, the API should be |
60 | organized and optimized so that the user only needs to know a minimum of the |
61 | API's functionality in order to accomplish the most common tasks. Furthermore, |
62 | that minimum should be easily discoverable in simple synopses and examples. |
63 | |
64 | =head2 Extensible API and backend |
65 | |
66 | Without breaking or, in as many cases as possible I<knowing>, existing backend |
67 | implementation details, the functionality of DBIx::Class should be extensible. |
68 | Both the API (new contact points) and backend (new datastores, etc) should be |
69 | extended knowing a simple API for doing so. This implies that as many pieces as |
70 | possible of the backend functionality should be overridable separate from every |
71 | other piece. |
72 | |
73 | =head1 RESTRICTIONS |
74 | |
75 | Fill this part in. |
76 | |
77 | =head1 RELATIONAL THEORY |
78 | |
79 | (B<Author's note:> To understand the fundamental underpinnings of DBIx::Class |
80 | 0.09's choice of features, it is necessary to have a common understanding of |
81 | relational theory. I recommend that everyone at least read this section once in |
82 | order to be familiar with the terms I use throughout this document.) |
83 | |
84 | Relational theory (calculus or algebra - the difference is esoteric) is, at its |
85 | roots, all about set theory and set manipulations. Each row in a table (or |
86 | tuple) is an element of a set. The various clause (or operations) in a SQL |
87 | statement can be viewed as set manipulators that take one or more sets of tuples |
88 | as input and provide a set of tuples as output. |
89 | |
90 | A SQL statement has many clauses and they are evaluated in a very specific order |
91 | that is different from the order they are presented. (As mutations share all of |
92 | their clauses with queries and evaluate in the same order, only queries will be |
93 | discussed 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 |
100 | parenthetical 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 | |
118 | An ORM must provide some very basic features. They are, in essence, the ability |
119 | to: |
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 | |
129 | These functions are generally achieved by providing some API to the SELECT |
130 | statement that returns a collection of objects. These objects then allow for |
131 | updating and deleting. The same API that allows for SELECT also, generally, will |
132 | allow for creation and, possibly, deletion. Most ORMs do this modelling by |
133 | mapping a class to a table and an instance of that class to a given row in that |
134 | table. |
135 | |
136 | DBIx::Class takes a different approach. Given rows in a table are represented by |
137 | objects, but the table as a whole is also represented by an object. There is no |
138 | class that represents the table in itself. Instead, there is a class that is |
139 | used to instantiate the rows of a table and another class that is used to |
140 | instantiate objects that represent SQL clauses for statements against that |
141 | table. The former is the Row class and the latter is the ResultSet class. This |
142 | separation allows for greater expressivity when dealing with a given table. |
143 | |
144 | DBIx::Class 0.09 extends these concepts by adding a third layer - the source. |
145 | |
146 | (Expand here.) |
147 | |
148 | =head3 Sources |
149 | |
150 | A source, at its simplest, is the representation of a single table in a |
151 | relational database. For example, the table `artists`. But, a source can be |
152 | much more than that. Within a relational database, "`artists JOIN cds`" forms a |
153 | source containing the columns of both `artists` and `cds`. Taken to the logical |
154 | extreme, the FROM clause of a query forms a single source. A subquery can also |
155 | be viewed as a source. (In fact, any table or join can be viewed as the subquery |
156 | "(SELECT * FROM table) AS table".) |
157 | |
158 | =head3 Resultsets |
159 | |
160 | The resultset is arguably the single most important breakthrough in DBIx::Class. |
161 | It allows for the gradual building of a SQL statement and reuse of that building |
162 | for more than just SELECT statements. In addition to being able to separate |
163 | responsibilites by letting different pieces of an application (such as security) |
164 | decorate the resultset appropriately, a resultset can also be reused for various |
165 | needs. The same resultset can be used for a query, a mass update, a mass delete, |
166 | or anything else. |
167 | |
168 | Under the hood, a resultset has a representation for each SQL clause. Each usage |
169 | of the resultset will take the clauses that make sense for that usage and leave |
170 | the others. |
171 | |
172 | (Expand here, detailing each usage of a resultset and the clauses that each |
173 | uses.) |
174 | |
175 | =head3 Rows |
176 | |
177 | Traditionally, the row object is a hashref representing a row in a table. This |
178 | representation is simple to implement, meets the 80/20 case, and completely |
179 | wrong. It fails when dealing with GROUP BY clauses and custom queries. The |
180 | proper treatment of a row object is that it represents the SELECT clause of the |
181 | resultset that generated it. In the 80/20 case, the SELECT clause will be all |
182 | the columns of the primary table being selected. By moving the defintion of the |
183 | row object into the resultset, the row object's definition is closer to its |
184 | usage. |
185 | |
186 | Under the hood, the row object is defined by using anonymous classes built with |
187 | roles, one role for each column. The roles for the columns are defined in the |
188 | definitions for each table. Those roles flow from the source(s), through the |
189 | resultset and into the row objects. |
190 | |
191 | =head2 Queries as streams |
192 | |
193 | A grouping of data can be viewed as either a collection or a stream. The main |
194 | difference is that a collection is eager and a stream is lazy. For large |
195 | datasets, collections can be very expensive in terms of memory and time (filling |
196 | that memory). Streams, on the other hand, defer loading anything into memory |
197 | until the last possible moment, but are easily convertible into a collection as |
198 | needed. (q.v. Higher Order Perl for more information.) |
199 | |
200 | =head2 |
201 | |
202 | =head1 TODO |
203 | |
204 | =over 4 |
205 | |
206 | =item * L</RESTRICTIONS> section needs to be filled in. |
207 | |
208 | =back |
209 | |
210 | =head1 AUTHOR(S) |
211 | |
212 | robkinyon: Rob Kinyon C<< <rkinyon@cpan.org> >> |
213 | |
214 | =head1 LICENSE |
215 | |
216 | You may distribute this code under the same terms as Perl itself. |
217 | |
218 | =cut |