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