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
8 ;;;; Tests for the CLSQL Functional Data Definition Language
11 ;;;; This file is part of CLSQL.
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 ;;;; ======================================================================
18 (in-package #:clsql-tests)
20 #.(clsql:locally-enable-sql-reader-syntax)
25 ;; list current tables
26 (deftest :fddl/table/1
27 (sort (mapcar #'string-downcase
28 (clsql:list-tables :owner *test-database-user*))
30 ("addr" "big" "company" "ea_join" "employee" "type_bigint" "type_table"))
32 ;; create a table, test for its existence, drop it and test again
33 (deftest :fddl/table/2
34 (progn (clsql:create-table [foo]
38 ([comments] longchar)))
40 (clsql:table-exists-p [foo] :owner *test-database-user*)
42 (clsql:drop-table [foo] :if-does-not-exist :ignore)
43 (clsql:table-exists-p [foo] :owner *test-database-user*))))
46 ;; create a table, list its attributes and drop it
47 (deftest :fddl/table/3
49 (progn (clsql:create-table [foo]
53 ([comments] longchar)))
55 (sort (mapcar #'string-downcase
56 (clsql:list-attributes [foo]))
58 (clsql:drop-table [foo] :if-does-not-exist :ignore))))
59 "comments" "height" "id" "name")
61 (deftest :fddl/table/4
63 (clsql:table-exists-p "MyMixedCase")
65 (clsql:create-table "MyMixedCase" '(([a] integer)))
66 (clsql:table-exists-p "MyMixedCase"))
68 (clsql:drop-table "MyMixedCase")
69 (clsql:table-exists-p "MyMixedCase")))
72 (deftest :fddl/table/5
75 (clsql:create-table "MyMixedCase" '(([a] integer)))
76 (clsql:execute-command "insert into MyMixedCase values (5)")
77 (clsql:insert-records :into "MyMixedCase" :values '(6))
78 (clsql:select [a] :from "MyMixedCase" :order-by '((a :asc))))
79 (clsql:drop-table "MyMixedCase"))
82 (deftest :fddl/attributes/1
85 (mapcar #'string-downcase
86 (clsql:list-attributes [employee]
87 :owner *test-database-user*))
89 "bd_utime" "birthday" "ecompanyid" "email" "emplid" "first_name" "groupid" "height"
90 "last_name" "managerid" "married")
92 (deftest :fddl/attributes/2
95 (mapcar #'(lambda (a) (string-downcase (car a)))
96 (clsql:list-attribute-types [employee]
97 :owner *test-database-user*))
99 "bd_utime" "birthday" "ecompanyid" "email" "emplid" "first_name" "groupid" "height"
100 "last_name" "managerid" "married")
102 ;; Attribute types are vendor specific so need to test a range
103 (deftest :fddl/attributes/3
104 (and (member (clsql:attribute-type [emplid] [employee]) '(:int :integer :int4 :number)) t)
107 (deftest :fddl/attributes/4
108 (multiple-value-bind (type length scale nullable)
109 (clsql:attribute-type [first-name] [employee])
110 (values (clsql-sys:in type :varchar :varchar2) length scale nullable))
113 (deftest :fddl/attributes/5
114 (and (member (clsql:attribute-type [birthday] [employee]) '(:datetime :timestamp :date)) t)
117 (deftest :fddl/attributes/6
118 (and (member (clsql:attribute-type [height] [employee]) '(:float :float8 :number)) t)
121 (deftest :fddl/attributes/7
122 (and (member (clsql:attribute-type [bd_utime] [employee]) '(:bigint :int8 :char)) t)
126 ;; create a view, test for existence, drop it and test again
127 (deftest :fddl/view/1
128 (progn (clsql:create-view [lenins-group]
129 :as [select [first-name] [last-name] [email]
131 :where [= [managerid] 1]])
133 (clsql:view-exists-p [lenins-group] :owner *test-database-user*)
135 (clsql:drop-view [lenins-group] :if-does-not-exist :ignore)
136 (clsql:view-exists-p [lenins-group] :owner *test-database-user*))))
139 ;; create a view, list its attributes and drop it
140 (when (clsql-sys:db-type-has-views? *test-database-underlying-type*)
141 (deftest :fddl/view/2
142 (progn (clsql:create-view [lenins-group]
143 :as [select [first-name] [last-name] [email]
145 :where [= [managerid] 1]])
147 (sort (mapcar #'string-downcase
148 (clsql:list-attributes [lenins-group]))
150 (clsql:drop-view [lenins-group] :if-does-not-exist :ignore)))
151 ("email" "first_name" "last_name")))
153 ;; create a view, select stuff from it and drop it
154 (deftest :fddl/view/3
155 (progn (clsql:create-view [lenins-group]
156 :as [select [first-name] [last-name] [email]
158 :where [= [managerid] 1]])
162 (clsql:select [first-name] [last-name] [email]
164 :where [= [last-name] "Lenin"])
166 (car (clsql:select [first-name] [last-name] [email]
168 :where [= [last-name] "Stalin"])))))
169 (clsql:drop-view [lenins-group] :if-does-not-exist :ignore)
170 (apply #'values result)))
171 nil ("Josef" "Stalin" "stalin@soviet.org"))
173 (deftest :fddl/view/4
174 (progn (clsql:create-view [lenins-group]
175 :column-list '([forename] [surname] [email])
176 :as [select [first-name] [last-name] [email]
178 :where [= [managerid] 1]])
182 (clsql:select [forename] [surname] [email]
184 :where [= [surname] "Lenin"])
186 (car (clsql:select [forename] [surname] [email]
188 :where [= [surname] "Stalin"])))))
189 (clsql:drop-view [lenins-group] :if-does-not-exist :ignore)
190 (apply #'values result)))
191 nil ("Josef" "Stalin" "stalin@soviet.org"))
193 ;; create an index, test for existence, drop it and test again
194 (deftest :fddl/index/1
195 (progn (clsql:create-index [bar] :on [employee] :attributes
196 '([first-name] [last-name] [email]) :unique t)
198 (clsql:index-exists-p [bar] :owner *test-database-user*)
200 (clsql:drop-index [bar] :on [employee]
201 :if-does-not-exist :ignore)
202 (clsql:index-exists-p [bar] :owner *test-database-user*))))
205 ;; create indexes with names as strings, symbols and in square brackets
206 (deftest :fddl/index/2
207 (let ((names '("foo" foo [foo]))
210 (clsql:create-index name :on [employee] :attributes '([emplid]))
211 (push (clsql:index-exists-p name :owner *test-database-user*) result)
212 (clsql:drop-index name :on [employee] :if-does-not-exist :ignore))
213 (apply #'values result))
216 ;; test list-indexes with keyword :ON
217 (deftest :fddl/index/3
219 (clsql:create-table [i3test] '(([a] (string 10))
221 (clsql:create-index [foo] :on [i3test] :attributes
223 (clsql:create-index [bar] :on [i3test] :attributes
226 (clsql:table-exists-p [i3test])
227 (clsql:index-exists-p [foo])
228 (clsql:index-exists-p [bar])
232 (clsql:list-indexes :on [i3test] :owner *test-database-user*))
235 (clsql:drop-index [bar] :on [i3test])
236 (clsql:drop-index [foo] :on [i3test])
237 (clsql:drop-table [i3test])
239 t t t ("bar" "foo") t)
241 ;; create an sequence, test for existence, drop it and test again
242 (deftest :fddl/sequence/1
243 (progn (clsql:create-sequence [foo])
245 (clsql:sequence-exists-p [foo] :owner *test-database-user*)
247 (clsql:drop-sequence [foo] :if-does-not-exist :ignore)
248 (clsql:sequence-exists-p [foo] :owner *test-database-user*))))
251 ;; create and increment a sequence
252 (deftest :fddl/sequence/2
254 (clsql:create-sequence [foo])
255 (setf val1 (clsql:sequence-next [foo]))
257 (< val1 (clsql:sequence-next [foo]))
258 (clsql:drop-sequence [foo] :if-does-not-exist :ignore)))
261 ;; explicitly set the value of a sequence
262 (deftest :fddl/sequence/3
264 (clsql:create-sequence [foo])
265 (clsql:set-sequence-position [foo] 5)
267 (clsql:sequence-next [foo])
268 (clsql:drop-sequence [foo] :if-does-not-exist :ignore)))
272 (let ((rows (clsql:select [*] :from [big] :field-names nil)))
277 (rest rows (cdr rest)))
278 ((= i (length rows)) t)
280 (int (first (car rest)))
281 (bigint (second (car rest))))
282 (when (and (or (eq *test-database-type* :oracle)
283 (and (eq *test-database-type* :odbc)
284 (eq *test-database-underlying-type* :postgresql)))
286 (setf bigint (parse-integer bigint)))
287 (unless (and (eql int index)
288 (eql bigint (truncate max index)))
295 #.(clsql:restore-sql-reader-syntax-state)