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