r9804: * doc/ref-ooddl.xml: minor changes to syntax and examples entries
[clsql.git] / examples / clsql-tutorial.lisp
1 (asdf:operate 'asdf:load-op 'clsql)
2
3 (in-package #:clsql-user)
4
5 ;; You must set these variables to appropriate values. 
6 (defvar *tutorial-database-type* nil 
7   "Possible values are :postgresql,:postgresql-socket :mysql,
8 :oracle, :odbc, :aodbc or :sqlite")
9 (defvar *tutorial-database-name* "clsqltut"
10   "The name of the database we will work in.")
11 (defvar *tutorial-database-user* "" 
12   "The name of the database user we will work as.")
13 (defvar *tutorial-database-server* ""
14   "The name of the database server if required")
15 (defvar *tutorial-database-password* "" 
16   "The password if required")
17
18 (clsql:def-view-class employee ()
19   ((emplid
20     :db-kind :key
21     :db-constraints :not-null
22     :type integer
23     :initarg :emplid)
24    (first-name
25     :accessor first-name
26     :type (string 30)
27     :initarg :first-name)
28    (last-name
29     :accessor last-name
30     :type (string 30)
31     :initarg :last-name)
32    (email
33     :accessor employee-email
34     :type (string 100)
35     :initarg :email)
36    (companyid
37     :type integer)
38    (company
39     :accessor employee-company
40     :db-kind :join
41     :db-info (:join-class company
42                           :home-key companyid
43                           :foreign-key companyid
44                           :set nil))
45    (managerid
46     :type integer
47     :initarg :managerid)
48    (manager
49     :accessor employee-manager
50     :db-kind :join
51     :db-info (:join-class employee
52                           :home-key managerid
53                           :foreign-key emplid
54                           :set nil)))
55   (:base-table employee))
56
57 (clsql:def-view-class company ()
58   ((companyid
59     :db-kind :key
60     :db-constraints :not-null
61     :type integer
62     :initarg :companyid)
63    (name
64     :type (string 100)
65     :initarg :name)
66    (presidentid
67     :type integer
68     :initarg :presidentid)
69    (president
70     :reader president
71     :db-kind :join
72     :db-info (:join-class employee
73                           :home-key presidentid
74                           :foreign-key emplid
75                           :set nil))
76    (employees
77     :reader company-employees
78     :db-kind :join
79     :db-info (:join-class employee
80                           :home-key companyid
81                           :foreign-key companyid
82                           :set t)))
83   (:base-table company))
84
85 ;; Connect to the database (see the CLSQL documentation for vendor
86 ;; specific connection specs).
87 (case *tutorial-database-type*
88   ((:mysql :postgresql)
89    (clsql:connect `(,*tutorial-database-server* 
90                     ,*tutorial-database-name*
91                     ,*tutorial-database-user* 
92                     ,*tutorial-database-password*)
93                   :database-type *tutorial-database-type*))
94   ((:odbc :aodbc :oracle)
95    (clsql:connect `(,*tutorial-database-name* 
96                     ,*tutorial-database-user* 
97                     ,*tutorial-database-password*)
98                   :database-type *tutorial-database-type*))
99   (:sqlite
100    (clsql:connect `(,*tutorial-database-name*)
101                   :database-type *tutorial-database-type*)))
102
103 ;; Record the sql going out, helps us learn what is going
104 ;; on behind the scenes
105 (clsql:start-sql-recording)
106
107 ;; Create the tables for our view classes
108 ;; First we drop them, ignoring any errors
109 (ignore-errors
110  (clsql:drop-view-from-class 'employee)
111  (clsql:drop-view-from-class 'company))
112
113 (clsql:create-view-from-class 'employee)
114 (clsql:create-view-from-class 'company)
115
116
117 ;; Create some instances of our view classes
118 (defvar company1 (make-instance 'company
119                               :companyid 1
120                               :name "Widgets Inc."
121                               ;; Lenin is president of Widgets Inc.
122                               :presidentid 1))
123
124 (defvar employee1 (make-instance 'employee
125                                :emplid 1
126                                :first-name "Vladamir"
127                                :last-name "Lenin"
128                                :email "lenin@soviet.org"
129                                :companyid 1))
130
131 (defvar employee2 (make-instance 'employee
132                                :emplid 2
133                                :first-name "Josef"
134                                :last-name "Stalin"
135                                :email "stalin@soviet.org"
136                                :companyid 1
137                                ;; Lenin manages Stalin (for now)
138                                :managerid 1))
139
140 (clsql:update-records-from-instance employee1)
141 (clsql:update-records-from-instance employee2)
142 (clsql:update-records-from-instance company1)
143
144 ;; lets use the functional sql interface 
145 (clsql:locally-enable-sql-reader-syntax)
146
147 (format t "The email address of ~A ~A is ~A"
148         (first-name employee1)
149         (last-name employee1)
150         (employee-email employee1))
151
152 (setf (employee-email employee1) "lenin-nospam@soviets.org")
153
154 ;; Update the database
155 (clsql:update-records-from-instance employee1)
156
157 (let ((new-lenin (car
158                   (clsql:select 'employee
159                               :where [= [slot-value 'employee 'emplid] 1]
160                               :flatp t))))
161   (format t "His new email is ~A"
162           (employee-email new-lenin)))
163
164
165 ;; Some queries
166
167 ;; all employees
168 (clsql:select 'employee)
169 ;; all companies
170 (clsql:select 'company)
171
172 ;; employees named Lenin
173 (clsql:select 'employee :where [= [slot-value 'employee 'last-name]
174                                 "Lenin"])
175
176 (clsql:select 'company :where [= [slot-value 'company 'name]
177                                "Widgets Inc."])
178
179 ;; Employees of Widget's Inc.
180 (clsql:select 'employee
181             :where [and [= [slot-value 'employee 'companyid]
182                            [slot-value 'company 'companyid]]
183                         [= [slot-value 'company 'name]
184                            "Widgets Inc."]])
185
186 ;; Same thing, except that we are using the employee
187 ;; relation in the company view class to do the join for us,
188 ;; saving us the work of writing out the SQL!
189 (company-employees company1)
190
191 ;; President of Widgets Inc.
192 (president company1)
193
194 ;; Manager of Josef Stalin
195 (employee-manager employee2)