r8850: remove usql files
[clsql.git] / doc / usql.xml
1 <?xml version='1.0' ?>
2 <!DOCTYPE book PUBLIC "-//OASIS//DTD DocBook XML V4.2//EN"
3                "http://www.oasis-open.org/docbook/xml/4.2/docbookx.dtd" [
4 <!ENTITY % myents SYSTEM "entities.inc">
5 %myents;
6 ]>
7
8 <chapter id="usql">
9   <title>UncommonSQL</title>
10
11   <sect1 id="usql-intro">
12     <title>Introduction</title>
13
14     <para>
15       The goal of this tutorial is to guide a new developer thru the
16       process of creating a set of &usql; classes providing a
17       Object-Oriented interface to persistent data stored in an &sql;
18       database.  We will assume that the reader is familiar with how
19       &sql; works, how relations (tables) should be structured, and
20       has created at least one &sql; application previously.  We will
21       also assume a minor level of experience with Common Lisp.
22     </para>
23
24     <para>
25       &usql; provides two different interfaces to &sql; databases, a
26       Functional interface, and an Object-Oriented interface.  The
27       Functional interface consists of a special syntax for embedded
28       &sql; expressions in Lisp, and provides lisp functions for &sql;
29       operations like <symbol>SELECT</symbol> and
30       <symbol>UPDATE</symbol>.  The object-oriented interface provides
31       a way for mapping Common Lisp Objects System (CLOS) objects into
32       databases and includes functions for inserting new objects,
33       querying objects, and removing objects.  Most applications will
34       use a combination of the two.
35     </para>
36
37     <para>
38       &usql; is based on the CommonSQL package from Xanalys, so the
39       documentation that Xanalys makes available online is useful for
40       &usql; as well.  It is suggested that developers new to &usql; check
41       their documentation out, as any differences between CommonSQL
42       and &usql; are minor. Xanalys makes the following documents
43       available:
44     </para>
45
46     <itemizedlist>
47       <listitem>
48         <para>
49           <ulink url="http://www.lispworks.com/reference/lw43/LWUG/html/lwuser-167.htm">
50             <citetitle>Xanalys LispWorks User Guide - The CommonSQL Package
51 </citetitle>
52           </ulink>
53         </para>
54       </listitem>
55
56       <listitem>
57         <para>
58           <ulink url="http://www.lispworks.com/reference/lw43/LWRM/html/lwref-383.htm">
59             <citetitle>Xanalys LispWorks Reference Manual - The SQL Package</citetitle>
60           </ulink>
61         </para>
62       </listitem>
63
64       <listitem>
65         <para>
66         <ulink url="http://www.ravenbrook.com/doc/2002/09/13/common-sql/">
67           <citetitle>CommonSQL Tutorial by Nick Levine</citetitle>
68         </ulink>
69         </para>
70       </listitem>
71     </itemizedlist>
72   </sect1>
73
74   <sect1>
75     <title>Data Modeling with UncommonSQL</title>
76
77     <para>
78       Before we can create, query and manipulate &usql; objects, we
79       need to define our data model as noted by Philip Greenspun
80       <footnote>
81         <para>
82         <ulink
83          url="http://www.arsdigita.com/books/sql/data-modeling.html">
84           <citetitle>Philip Greenspun's "SQL For Web Nerds" - Data
85           Modeling</citetitle>
86         </ulink>
87         </para>
88       </footnote>
89     </para>
90
91     <para>
92       When data modeling, you are telling the RDBMS the following: 
93     </para>
94
95     <itemizedlist>
96       <listitem>
97         <para>What elements of the data you will store</para>
98       </listitem> 
99       <listitem>
100         <para>How large each element can be</para>
101       </listitem>
102       <listitem>
103         <para>What kind of information each element can contain</para>
104       </listitem>
105       <listitem>
106         <para>What elements may be left blank</para> 
107       </listitem>
108       <listitem>
109         <para>Which elements are constrained to a fixed range</para>
110       </listitem>
111       <listitem>
112         <para>Whether and how various tables are to be linked</para>
113       </listitem>
114     </itemizedlist>
115
116     <para>
117       With &sql; database one would do this by defining a set of
118       relations, or tables, followed by a set of queries for joining
119       the tables together in order to construct complex records.
120       However, with &usql; we do this by defining a set of CLOS
121       classes, specifying how they will be turned into tables, and how
122       they can be joined to one another via relations between their
123       attributes.  The &sql; tables, as well as the queries for
124       joining them together are created for us automatically, saving
125       us from dealing with some of the tedium of &sql;.
126     </para>
127
128     <para>
129       Let us start with a simple example of two &sql; tables, and the
130       relations between them.
131     </para>
132
133 <programlisting>
134 CREATE TABLE EMPLOYEE (
135        emplid           NOT NULL        number(38),
136        first_name       NOT NULL        varchar2(30),
137        last_name        NOT NULL        varchar2(30),
138        emall                            varchar2(100),
139        companyid        NOT NULL        number(38),
140        managerid                        number(38)
141 )
142
143 CREATE TABLE COMPANY (
144        companyid        NOT NULL        number(38),
145        name             NOT NULL        varchar2(100),
146        presidentid      NOT NULL        number(38)
147 )
148 </programlisting>
149
150 <para>
151 This is of course the canonical &sql; tutorial example, "The Org Chart".
152 </para>
153
154 <para>
155 In &usql;, we would have two "view classes" (a fancy word for a class
156 mapped into a database).  They would be defined as follows:
157 </para>
158
159 <programlisting>
160 (clsql-usql:def-view-class employee ()
161   ((emplid
162     :db-kind :key
163     :db-constraints :not-null
164     :type integer
165     :initarg :emplid)
166    (first-name
167     :accessor first-name
168     :type (string 30)
169     :initarg :first-name)
170    (last-name
171     :accessor last-name
172     :type (string 30)
173     :initarg :last-name)
174    (email
175     :accessor employee-email
176     :type (string 100)
177     :nulls-ok t
178     :initarg :email)
179    (companyid
180     :type integer)
181    (managerid
182     :type integer
183     :nulls-ok t))
184   (:base-table employee))
185
186 (clsql-usql:def-view-class company ()
187   ((companyid
188     :db-type :key
189     :db-constraints :not-null
190     :type integer
191     :initarg :companyid)
192    (name
193     :type (string 100)
194     :initarg :name)
195    (presidentid
196     :type integer))
197   (:base-table company))
198 </programlisting>
199
200 <para>
201   The <function>DEF-VIEW-CLASS</function> macro is just like the
202   normal CLOS <function>DEFCLASS</function> macro, except that it
203   handles several slot options that <function>DEFCLASS</function>
204   doesn't.  These slot options have to do with the mapping of the slot
205   into the database.  We only use a few of the slot options in the
206   above example, but there are several others.
207 </para>
208
209 <itemizedlist>
210
211   <listitem><para>
212   <symbol>:column</symbol> - The name of the &sql; column this slot is stored in.
213     Defaults to the slot name.  If the slot name is not a valid &sql;
214     identifier, it is escaped, so foo-bar becomes foo_bar.
215   </para></listitem>
216
217   <listitem>
218     <para> 
219       <symbol>:db-kind</symbol> - The kind of database mapping which
220       is performed for this slot.  <symbol>:base</symbol> indicates
221       the slot maps to an ordinary column of the database view.
222       <symbol>:key</symbol> indicates that this slot corresponds to
223       part of the unique keys for this view, <symbol>:join</symbol>
224       indicates a join slot representing a relation to another view
225       and :virtual indicates that this slot is an ordinary CLOS slot.
226       Defaults to <symbol>:base</symbol>. </para></listitem>
227
228   <listitem>
229     <para>
230       <symbol>:db-reader</symbol> - If a string, then when reading
231       values from the database, the string will be used for a format
232       string, with the only value being the value from the database.
233       The resulting string will be used as the slot value.  If a
234       function then it will take one argument, the value from the
235       database, and return the value that should be put into the slot.
236       </para></listitem>
237
238   <listitem>
239     <para>
240       <symbol>:db-writer</symbol> - If a string, then when reading
241       values from the slot for the database, the string will be used
242       for a format string, with the only value being the value of the
243       slot.  The resulting string will be used as the column value in
244       the database.  If a function then it will take one argument, the
245       value of the slot, and return the value that should be put into
246       the database.</para></listitem>
247
248   <listitem>
249     <para>
250       <symbol>:db-type</symbol> - A string which will be used as the
251       type specifier for this slots column definition in the database.
252       </para></listitem>
253
254   <listitem>
255     <para>
256       <symbol>:nulls-ok</symbol> - If &t;, all &sql; &null; values
257       retrieved from the database become nil; if &nil;, all &null;
258       values retrieved are converted by
259       <function>DATABASE-NULL-VALUE</function>. </para></listitem>
260
261   <listitem>
262     <para>
263       <symbol>:db-info</symbol> - A join specification.
264       </para></listitem>
265 </itemizedlist>
266
267 <para>
268   In our example each table as a primary key attribute, which is
269   required to be unique.  We indicate that a slot is part of the
270   primary key (&usql; supports multi-field primary keys) by specifying
271   the <symbol>:db-kind</symbol> key slot option.
272 </para>
273
274 <para>
275   The &sql; type of a slot when it is mapped into the database is
276   determined by the <symbol>:type</symbol> slot option.  The argument
277   for the <symbol>:type</symbol> option is a Common Lisp datatype.
278   The &usql; framework will determine the appropriate mapping
279   depending on the database system the table is being created in.  If
280   we really wanted to determine what &sql; type was used for a slot,
281   we could specify a <symbol>:db-type</symbol> option like
282   "NUMBER(38)" and we would be guaranteed that the slot would be
283   stored in the database as a NUMBER(38).  This is not recomended
284   because it could makes your view class unportable across database
285   systems.
286 </para>
287
288 <para>
289   <function>DEF-VIEW-CLASS</function> also supports some class
290   options, like <symbol>:base-table</symbol>.  The
291   <symbol>:base-table</symbol> option specifies what the table name
292   for the view class will be when it is mapped into the database.
293 </para>
294   </sect1>
295
296 <sect1 id="usql-rel">
297 <title>Class Relations</title> 
298
299 <para>
300 In an &sql; only application, the <symbol>EMPLOYEE</symbol> and
301 <symbol>COMPANY</symbol> tables can be queried to determine things
302 like, "Who is Vladamir's manager?", What company does Josef work
303 for?", and "What employees work for Widgets Inc.".  This is done by
304 joining tables with an &sql; query.
305 </para>
306
307 <para>
308 Who works for Widgets Inc.?
309 </para>
310
311 <programlisting>
312 SELECT first_name, last_name FROM employee, company
313        WHERE employee.companyid = company.companyid
314              AND company.company_name = "Widgets Inc."
315 </programlisting>
316
317 <para>
318 Who is Vladamir's manager?
319 </para>
320
321 <programlisting>
322 SELECT managerid FROM employee
323        WHERE employee.first_name = "Vladamir"
324              AND employee.last_name = "Lenin"
325 </programlisting>
326
327 <para>
328 What company does Josef work for?
329 </para>
330
331 <programlisting>
332 SELECT company_name FROM company, employee
333        WHERE employee.first_name = "Josef"
334              AND employee.last-name = "Stalin"
335              AND employee.companyid = company.companyid
336 </programlisting>
337
338 <para>
339 With &usql; however we do not need to write out such queries because
340 our view classes can maintain the relations between employees and
341 companies, and employees to their managers for us.  We can then access
342 these relations like we would any other attribute of an employee or
343 company object.  In order to do this we define some join slots for our
344 view classes.
345 </para>
346
347 <para>
348 What company does an employee work for?  If we add the following slot
349 definition to the employee class we can then ask for it's
350 <symbol>COMPANY</symbol> slot and get the appropriate result.
351 </para>
352
353 <programlisting>
354     ;; In the employee slot list
355     (company
356       :accessor employee-company
357       :db-kind :join
358       :db-info (:join-class company
359                 :home-key companyid
360                 :foreign-key companyid
361                 :set nil))
362 </programlisting>
363
364 <para>
365 Who are the employees of a given company?  And who is the president of
366 it? We add the following slot definition to the company view class and
367 we can then ask for it's <symbol>EMPLOYEES</symbol> slot and get the
368 right result.
369 </para>
370
371 <programlisting>
372       ;; In the company slot list
373       (employees
374         :reader company-employees
375         :db-kind :join
376         :db-info (:join-class employee
377                   :home-key companyid
378                   :foreign-key companyid
379                   :set t))
380
381        (president
382         :reader president
383         :db-kind :join
384         :db-info (:join-class employee
385                   :home-key presidentid
386                   :foreign-key emplid
387                   :set nil))
388 </programlisting>
389
390 <para>
391 And lastly, to define the relation between an employee and their
392 manager:
393 </para>
394
395 <programlisting>
396         ;; In the employee slot list
397        (manager
398         :accessor employee-manager
399         :db-kind :join
400         :db-info (:join-class employee
401                   :home-key managerid
402                   :foreign-key emplid
403                   :set nil))
404 </programlisting>
405
406 <para>
407 &usql; join slots can represent one-to-one, one-to-many, and
408 many-to-many relations.  Above we only have one-to-one and one-to-many
409 relations, later we will explain how to model many-to-many relations.
410 First, let's go over the slot definitions and the available options.
411 </para>
412
413 <para>
414 In order for a slot to be a join, we must specify that it's
415 <symbol>:db-kind</symbol> <symbol>:join</symbol>, as opposed to
416 <symbol>:base</symbol> or <symbol>:key</symbol>.  Once we do that, we
417 still need to tell &usql; how to create the join statements for the
418 relation.  This is what the <symbol>:db-info</symbol> option does.  It
419 is a list of keywords and values.  The available keywords are:
420 </para>
421
422 <itemizedlist>
423   <listitem>
424     <para>
425       <symbol>:join-class</symbol> - The view class to which we want
426       to join.  It can be another view class, or the same view class
427       as our object.</para></listitem>
428
429   <listitem>
430     <para>
431       <symbol>:home-key</symbol> - The slot(s) in the immediate object
432       whose value will be compared to the foreign-key slot(s) in the
433       join-class in order to join the two tables.  It can be a single
434       slot-name, or it can be a list of slot names.</para></listitem>
435       
436   <listitem>
437     <para>
438       <symbol>:foreign-key</symbol> - The slot(s) in the join-class
439       which will be compared to the value(s) of the home-key.
440       </para></listitem>
441
442   <listitem>
443     <para>
444       <symbol>:set</symbol> - A boolean which if false, indicates that
445       this is a one-to-one relation, only one object will be returned.
446       If true, than this is a one-to-many relation, a list of objects
447       will be returned when we ask for this slots value.
448       </para></listitem>
449 </itemizedlist>
450
451 <para>
452 There are other :join-info options available in &usql;, but we will
453 save those till we get to the many-to-many relation examples.
454 </para>
455
456 </sect1>
457
458 <sect1 id="usql-creat">
459 <title>Object Creation</title>
460
461 <para>
462 Now that we have our model laid out, we should create some object.
463 Let us assume that we have a database connect set up already.  We
464 first need to create our tables in the database:
465 </para>
466
467 <para>
468 Note: the file <filename>doc/usql-tutorial.lisp</filename> contains
469 view class definitions which you can load into your list at this point
470 in order to play along at home.
471 </para>
472
473 <programlisting>
474 (clsql-usql:create-view-from-class 'employee)
475 (clsql-usql:create-view-from-class 'company)
476 </programlisting>
477
478 <para>
479 Then we will create our objects.  We create them just like you would
480 any other CLOS object:
481 </para>
482
483 <programlisting>
484 (defvar employee1 (make-instance 'employee
485                                :emplid 1
486                                :first-name "Vladamir"
487                                :last-name "Lenin"
488                                :email "lenin@soviet.org"))
489
490 (defvar company1 (make-instance 'company
491                               :companyid 1
492                               :name "Widgets Inc."))
493                               
494
495 (defvar employee2 (make-instance 'employee
496                                :emplid 2
497                                :first-name "Josef"
498                                :last-name "Stalin"
499                                :email "stalin@soviet.org"))
500 </programlisting>
501
502 <para>
503 In order to insert an objects into the database we use the
504 <function>UPDATE-RECORDS-FROM-INSTANCE</function> function as follows:
505 </para>
506
507 <programlisting>
508 (clsql-usql:update-records-from-instance employee1)
509 (clsql-usql:update-records-from-instance employee2)
510 (clsql-usql:update-records-from-instance company1)
511 </programlisting>
512
513 <para>
514 Now we can set up some of the relations between employees and
515 companies, and their managers.  The
516 <function>ADD-TO-RELATION</function> method provides us with an easy
517 way of doing that.  It will update both the relation slot, as well as
518 the home-key and foreign-key slots in both objects in the relation.
519 </para>
520
521 <programlisting>
522 ;; Lenin manages Stalin (for now)
523 (clsql-usql:add-to-relation employee2 'manager employee1)
524
525 ;; Lenin and Stalin both work for Widgets Inc.
526 (clsql-usql:add-to-relation company1 'employees employee1)
527 (clsql-usql:add-to-relation company1 'employees employee2)
528
529 ;; Lenin is president of Widgets Inc.
530 (clsql-usql:add-to-relation company1 'president employee1)
531 </programlisting>
532
533 <para>
534   After you make any changes to an object, you have to specifically
535   tell &usql; to update the &sql; database.  The
536   <function>UPDATE-RECORDS-FROM-INSTANCE</function> method will write
537   all of the changes you have made to the object into the database.
538 </para>
539
540 <para>
541   Since &usql; objects re just normal CLOS objects, we can manipulate
542   their slots just like any other object.  For instance, let's say
543   that Lenin changes his email because he was getting too much spam
544   from the German Socialists.
545 </para>
546
547 <programlisting>
548 ;; Print Lenin's current email address, change it and save it to the
549 ;; database.  Get a new object representing Lenin from the database
550 ;; and print the email
551
552 ;; This lets us use the functional &usql; interface with [] syntax
553 (clsql-usql:locally-enable-sql-reader-syntax)
554
555 (format t "The email address of ~A ~A is ~A"
556         (first-name employee1)
557         (last-name employee1)
558         (employee-email employee1))
559
560 (setf (employee-email employee1) "lenin-nospam@soviets.org")
561
562 ;; Update the database
563 (clsql-usql:update-records-from-instance employee1)
564
565 (let ((new-lenin (car (clsql-usql:select 'employee
566                         :where [= [slot-value 'employee 'emplid] 1]))))
567       (format t "His new email is ~A"
568           (employee-email new-lenin)))
569 </programlisting>
570
571 <para>
572   Everything except for the last <function>LET</function> expression
573   is already familiar to us by now.  To understand the call to
574   <function>CLSQL-USQL:SELECT</function> we need to discuss the
575   Functional &sql; interface and it's integration with the Object
576   Oriented interface of &usql;.
577 </para>
578
579 </sect1>
580
581 <sect1 id="usql-find">
582 <title>Finding Objects</title>
583
584 <para>
585   Now that we have our objects in the database, how do we get them out
586   when we need to work with them?  &usql; provides a functional
587   interface to &sql;, which consists of a special Lisp reader macro
588   and some functions.  The special syntax allows us to embed &sql; in
589   lisp expressions, and lisp expressions in &sql;, with ease.
590 </para>
591
592 <para>
593   Once we have turned on the syntax with the expression:
594 </para>
595
596 <programlisting>
597 (clsql-usql:locally-enable-sql-reader-syntax)
598 </programlisting>
599
600 <para>
601   We can start entering fragments of &sql; into our lisp reader.  We
602   will get back objects which represent the lisp expressions.  These
603   objects will later be compiled into &sql; expressions that are
604   optimized for the database backed we are connected to.  This means
605   that we have a database independent &sql; syntax.  Here are some
606   examples:
607 </para>
608
609 <programlisting>
610 ;; an attribute or table name
611 [foo] => #&lt;CLSQL-USQL-SYS::SQL-IDENT-ATTRIBUTE FOO>
612
613 ;; a attribute identifier with table qualifier
614 [foo bar] => #&lt;CLSQL-USQL-SYS::SQL-IDENT-ATTRIBUTE FOO.BAR>
615
616 ;; a attribute identifier with table qualifier
617 [= "Lenin" [first_name]] =>
618    #&lt;CLSQL-USQL-SYS::SQL-RELATIONAL-EXP ('Lenin' = FIRST_NAME)>
619
620 [&lt; [emplid] 3] =>
621    #&lt;CLSQL-USQL-SYS::SQL-RELATIONAL-EXP (EMPLID &lt; 3)>
622
623 [and [&lt; [emplid] 2] [= [first_name] "Lenin"]] =>
624    #&lt;CLSQL-USQL-SYS::SQL-RELATIONAL-EXP ((EMPLID &lt; 2) AND
625                                      (FIRST_NAME = 'Lenin'))>
626
627
628 ;; If we want to reference a slot in an object we can us the
629 ;;  SLOT-VALUE sql extension
630 [= [slot-value 'employee 'emplid] 1] =>
631    #&lt;CLSQL-USQL-SYS::SQL-RELATIONAL-EXP (EMPLOYEE.EMPLID = 1)>
632
633 [= [slot-value 'employee 'emplid]
634    [slot-value 'company 'presidentid]] =>
635    #&lt;CLSQL-USQL-SYS::SQL-RELATIONAL-EXP (EMPLOYEE.EMPLID = COMPANY.PRESIDENTID)>
636 </programlisting>
637
638 <para>
639   The <function>SLOT-VALUE</function> operator is important because it
640   let's us query objects in a way that is robust to any changes in the
641   object->table mapping, like column name changes, or table name
642   changes.  So when you are querying objects, be sure to use the
643   <function>SLOT-VALUE</function> &sql; extension.
644 </para>
645
646 <para>
647   Since we can now formulate &sql; relational expression which can be
648   used as qualifiers, like we put after the <symbol>WHERE</symbol>
649   keyword in &sql; statements, we can start querying our objects.
650   &usql; provides a function <symbol>SELECT</symbol> which can return
651   use complete objects from the database which conform to a qualifier,
652   can be sorted, and various other &sql; operations.
653 </para>
654
655 <para>
656   The first argument to <symbol>SELECT</symbol> is a class name.  it
657   also has a set of keyword arguments which are covered in the
658   documentation.  For now we will concern ourselves only with the
659   :where keyword.  Select returns a list of objects, or nil if it
660   can't find any.  It's important to remember that it always returns a
661   list, so even if you are expecting only one result, you should
662   remember to extract it from the list you get from
663   <symbol>SELECT</symbol>.
664 </para>
665
666 <programlisting>
667 ;; all employees
668 (clsql-usql:select 'employee)
669 ;; all companies
670 (clsql-usql:select 'company)
671
672 ;; employees named Lenin
673 (clsql-usql:select 'employee :where [= [slot-value 'employee 'last-name]
674                                 "Lenin"])
675
676 (clsql-usql:select 'company :where [= [slot-value 'company 'name]
677                                "Widgets Inc."])
678
679 ;; Employees of Widget's Inc.
680 (clsql-usql:select 'employee
681             :where [and [= [slot-value 'employee 'companyid]
682                            [slot-value 'company 'companyid]]
683                         [= [slot-value 'company 'name]
684                            "Widgets Inc."]])
685
686 ;; Same thing, except that we are using the employee
687 ;; relation in the company view class to do the join for us,
688 ;; saving us the work of writing out the &sql;!
689 (company-employees company1)
690
691 ;; President of Widgets Inc.
692 (president company1)
693
694 ;; Manager of Josef Stalin
695 (employee-manager employee2)
696 </programlisting>
697
698 </sect1>
699
700 <sect1 id="usql-del">
701 <title>Deleting Objects</title>
702
703 <para>
704   Now that we know how to create objects in our database, manipulate
705   them and query them (including using our predefined relations to
706   save us the trouble writing alot of &sql;) we should learn how to
707   clean up after ourself.  It's quite simple really. The function
708   <function>DELETE-INSTANCE-RECORDS</function> will remove an object
709   from the database.  However, when we remove an object we are
710   responsible for making sure that the database is left in a correct
711   state.
712 </para>
713
714 <para>
715   For example, if we remove a company record, we need to either remove
716   all of it's employees or we need to move them to another company.
717   Likewise if we remove an employee, we should make sure to update any
718   other employees who had them as a manager.
719 </para>
720
721 </sect1>
722
723 <sect1 id="usql-concl">
724 <title>Conclusion</title>
725
726 <para>
727   There are alot more nooks and crannies to &usql;, some of which are
728   covered in the Xanalys documents we refered to earlier, some are
729   not.  The best documentation at this time is still the source code
730   for &usql; itself and the inline documentation for it's various
731   function.
732 </para>
733
734 </sect1>
735
736 </chapter>