r9427: 22 May 2004 Kevin Rosenberg
[clsql.git] / tests / test-fddl.lisp
1 ;;;; -*- Mode: LISP; Syntax: ANSI-Common-Lisp; Base: 10 -*-
2 ;;;; ======================================================================
3 ;;;; File:     test-fddl.lisp
4 ;;;; Authors:  Marcus Pearce <m.t.pearce@city.ac.uk> and Kevin Rosenberg
5 ;;;; Created:  30/03/2004
6 ;;;; Updated:  $Id$
7 ;;;;
8 ;;;; Tests for the CLSQL Functional Data Definition Language
9 ;;;; (FDDL).
10 ;;;;
11 ;;;; This file is part of CLSQL.
12 ;;;;
13 ;;;; CLSQL users are granted the rights to distribute and use this software
14 ;;;; as governed by the terms of the Lisp Lesser GNU Public License
15 ;;;; (http://opensource.franz.com/preamble.html), also known as the LLGPL.
16 ;;;; ======================================================================
17
18 (in-package #:clsql-tests)
19
20 #.(clsql:locally-enable-sql-reader-syntax)
21
22 (setq *rt-fddl*
23       '(
24         
25 ;; list current tables 
26 (deftest :fddl/table/1
27     (apply #'values 
28            (sort (mapcar #'string-downcase
29                          (clsql:list-tables :owner *test-database-user*))
30                  #'string<))
31   "addr" "company" "ea_join" "employee" "type_bigint" "type_table")
32
33 ;; create a table, test for its existence, drop it and test again 
34 (deftest :fddl/table/2
35     (progn (clsql:create-table  [foo]
36                                '(([id] integer)
37                                  ([height] float)
38                                  ([name] (string 24))
39                                  ([comments] longchar)))
40            (values
41             (clsql:table-exists-p [foo] :owner *test-database-user*)
42             (progn
43               (clsql:drop-table [foo] :if-does-not-exist :ignore)
44               (clsql:table-exists-p [foo] :owner *test-database-user*))))
45   t nil)
46
47 ;; create a table, list its attributes and drop it 
48 (deftest :fddl/table/3
49     (apply #'values 
50            (progn (clsql:create-table  [foo]
51                                       '(([id] integer)
52                                         ([height] float)
53                                         ([name] (char 255))
54                                         ([comments] longchar)))
55                   (prog1
56                       (sort (mapcar #'string-downcase
57                                     (clsql:list-attributes [foo]))
58                             #'string<)
59                     (clsql:drop-table [foo] :if-does-not-exist :ignore))))
60   "comments" "height" "id" "name")
61
62 (deftest :fddl/attributes/1
63     (apply #'values
64            (sort 
65             (mapcar #'string-downcase
66                     (clsql:list-attributes [employee]
67                                            :owner *test-database-user*))
68             #'string<))
69   "birthday" "ecompanyid" "email" "emplid" "first_name" "groupid" "height"
70   "last_name" "managerid" "married")
71
72 (deftest :fddl/attributes/2
73     (apply #'values 
74            (sort 
75             (mapcar #'(lambda (a) (string-downcase (car a)))
76                     (clsql:list-attribute-types [employee]
77                                                :owner *test-database-user*))
78             #'string<))
79   "birthday" "ecompanyid" "email" "emplid" "first_name" "groupid" "height"
80   "last_name" "managerid" "married")
81
82 ;; Attribute types are vendor specific so need to test a range
83 (deftest :fddl/attributes/3
84     (and (member (clsql:attribute-type [emplid] [employee]) '(:int :integer :int4 :number)) t)
85   t)
86
87 (deftest :fddl/attributes/4
88     (multiple-value-bind (type length scale nullable)
89         (clsql:attribute-type [first-name] [employee])
90       (values (clsql-sys:in type :varchar :varchar2) length scale nullable))
91   t 30 nil 1)
92
93 (deftest :fddl/attributes/5
94     (and (member (clsql:attribute-type [birthday] [employee]) '(:datetime :timestamp :date)) t)
95   t)
96
97 (deftest :fddl/attributes/6
98     (and (member (clsql:attribute-type [height] [employee]) '(:float :float8 :number)) t)
99   t)
100
101
102
103 ;; create a view, test for existence, drop it and test again
104 (deftest :fddl/view/1
105     (progn (clsql:create-view [lenins-group]
106                               :as [select [first-name] [last-name] [email]
107                                           :from [employee]
108                                           :where [= [managerid] 1]])
109            (values  
110             (clsql:view-exists-p [lenins-group] :owner *test-database-user*)
111             (progn
112               (clsql:drop-view [lenins-group] :if-does-not-exist :ignore)
113               (clsql:view-exists-p [lenins-group] :owner *test-database-user*))))
114   t nil)
115   
116   ;; create a view, list its attributes and drop it 
117 (when (clsql-sys:db-type-has-views? *test-database-underlying-type*)
118   (deftest :fddl/view/2
119       (progn (clsql:create-view [lenins-group]
120                                 :as [select [first-name] [last-name] [email]
121                                             :from [employee]
122                                             :where [= [managerid] 1]])
123              (prog1
124                  (sort (mapcar #'string-downcase
125                                (clsql:list-attributes [lenins-group]))
126                        #'string<)
127                (clsql:drop-view [lenins-group] :if-does-not-exist :ignore)))
128     ("email" "first_name" "last_name")))
129   
130   ;; create a view, select stuff from it and drop it 
131 (deftest :fddl/view/3
132     (progn (clsql:create-view [lenins-group]
133                               :as [select [first-name] [last-name] [email]
134                                           :from [employee]
135                                           :where [= [managerid] 1]])
136            (let ((result 
137                   (list 
138                    ;; Shouldn't exist 
139                    (clsql:select [first-name] [last-name] [email]
140                                  :from [lenins-group]
141                                  :where [= [last-name] "Lenin"])
142                    ;; Should exist 
143                    (car (clsql:select [first-name] [last-name] [email]
144                                       :from [lenins-group]
145                                       :where [= [last-name] "Stalin"])))))
146              (clsql:drop-view [lenins-group] :if-does-not-exist :ignore)
147              (apply #'values result)))
148   nil ("Josef" "Stalin" "stalin@soviet.org"))
149   
150 (deftest :fddl/view/4
151     (progn (clsql:create-view [lenins-group]
152                               :column-list '([forename] [surname] [email])
153                               :as [select [first-name] [last-name] [email]
154                                           :from [employee]
155                                           :where [= [managerid] 1]])
156            (let ((result 
157                   (list
158                    ;; Shouldn't exist 
159                    (clsql:select [forename] [surname] [email]
160                                  :from [lenins-group]
161                                  :where [= [surname] "Lenin"])
162                    ;; Should exist 
163                    (car (clsql:select [forename] [surname] [email]
164                                       :from [lenins-group]
165                                       :where [= [surname] "Stalin"])))))
166              (clsql:drop-view [lenins-group] :if-does-not-exist :ignore)
167              (apply #'values result)))
168   nil ("Josef" "Stalin" "stalin@soviet.org"))
169
170 ;; create an index, test for existence, drop it and test again 
171 (deftest :fddl/index/1
172     (progn (clsql:create-index [bar] :on [employee] :attributes
173                               '([first-name] [last-name] [email]) :unique t)
174            (values
175             (clsql:index-exists-p [bar] :owner *test-database-user*)
176             (progn
177               (clsql:drop-index [bar] :on [employee]
178                                 :if-does-not-exist :ignore)
179               (clsql:index-exists-p [bar] :owner *test-database-user*))))
180   t nil)
181
182 ;; create indexes with names as strings, symbols and in square brackets 
183 (deftest :fddl/index/2
184     (let ((names '("foo" foo [foo]))
185           (result '()))
186       (dolist (name names)
187         (clsql:create-index name :on [employee] :attributes '([emplid]))
188         (push (clsql:index-exists-p name :owner *test-database-user*) result)
189         (clsql:drop-index name :on [employee] :if-does-not-exist :ignore))
190       (apply #'values result))
191   t t t)
192
193 ;; test list-table-indexes
194 (deftest :fddl/index/3
195     (progn
196       (clsql:create-table [i3test] '(([a] (string 10))
197                                      ([b] integer)))
198       (clsql:create-index [foo] :on [i3test] :attributes
199        '([b]) :unique nil)
200       (clsql:create-index [bar] :on [i3test] :attributes
201        '([a]) :unique t)
202       (values
203        (clsql:table-exists-p [i3test])
204        (clsql:index-exists-p [foo])
205        (clsql:index-exists-p [bar])
206        (sort 
207         (mapcar 
208          #'string-downcase
209          (clsql:list-table-indexes [i3test] :owner *test-database-user*))
210         #'string-lessp)
211        (progn
212          (clsql:drop-index [bar] :on [i3test])
213          (clsql:drop-index [foo] :on [i3test])
214          (clsql:drop-table [i3test])
215          t)))
216   t t t ("bar" "foo") t)
217
218 ;; create an sequence, test for existence, drop it and test again 
219 (deftest :fddl/sequence/1
220     (progn (clsql:create-sequence [foo])
221            (values
222             (clsql:sequence-exists-p [foo] :owner *test-database-user*)
223             (progn
224               (clsql:drop-sequence [foo] :if-does-not-exist :ignore)
225               (clsql:sequence-exists-p [foo] :owner *test-database-user*))))
226   t nil)
227
228 ;; create and increment a sequence
229 (deftest :fddl/sequence/2
230     (let ((val1 nil))
231       (clsql:create-sequence [foo])
232       (setf val1 (clsql:sequence-next [foo]))
233       (prog1
234           (< val1 (clsql:sequence-next [foo]))
235         (clsql:drop-sequence [foo] :if-does-not-exist :ignore)))
236   t)
237
238 ;; explicitly set the value of a sequence
239 (deftest :fddl/sequence/3
240     (progn
241       (clsql:create-sequence [foo])
242       (clsql:set-sequence-position [foo] 5)
243       (prog1
244           (clsql:sequence-next [foo])
245         (clsql:drop-sequence [foo] :if-does-not-exist :ignore)))
246   6)
247
248 ))
249
250 #.(clsql:restore-sql-reader-syntax-state)