Remove CVS $Id$ keyword
[clsql.git] / tests / test-syntax.lisp
1 ;;;; -*- Mode: LISP; Syntax: ANSI-Common-Lisp; Base: 10 -*-
2 ;;;; *************************************************************************
3 ;;;; FILE IDENTIFICATION
4 ;;;;
5 ;;;; Name:     clsql.asd
6 ;;;; Purpose:  Tests for the CLSQL Symbolic SQL syntax.
7 ;;;; Authors:  Marcus Pearce and Kevin M. Rosenberg
8 ;;;; Created:  March 2004
9 ;;;;
10 ;;;; CLSQL users are granted the rights to distribute and use this software
11 ;;;; as governed by the terms of the Lisp Lesser GNU Public License
12 ;;;; (http://opensource.franz.com/preamble.html), also known as the LLGPL.
13 ;;;; *************************************************************************
14
15 (in-package #:clsql-tests)
16
17 #.(clsql:locally-enable-sql-reader-syntax)
18
19
20 (setq *rt-syntax*
21       '(
22
23 (deftest :syntax/generic/1
24     (clsql:sql "foo")
25   "'foo'")
26
27 (deftest :syntax/generic/2
28     (clsql:sql 23)
29   "23")
30
31 (deftest :syntax/generic/3
32     (clsql:sql 'bar)
33   "BAR")
34
35 (deftest :syntax/generic/4
36     (clsql:sql '("ten" 10 ten))
37   "('ten',10,TEN)")
38
39 (deftest :syntax/generic/5
40     (clsql:sql ["SELECT FOO,BAR FROM BAZ"])
41   "SELECT FOO,BAR FROM BAZ")
42
43 (deftest :syntax/generic/6
44     (clsql:sql "What's up Doc?")
45   "'What''s up Doc?'")
46
47 (deftest :syntax/ident/1
48     (clsql:sql [foo])
49   "FOO")
50
51 (deftest :syntax/ident/2
52     (clsql:sql [foo bar])
53   "FOO.BAR")
54
55 (deftest :syntax/ident/3
56     (clsql:sql [foo :integer])
57   "FOO")
58
59 (deftest :syntax/ident/4
60     (clsql:sql [foo bar :integer])
61   "FOO.BAR")
62
63 (deftest :syntax/ident/5
64     (clsql:sql [foo "bar"])
65     "FOO \"bar\"")
66
67 (deftest :syntax/ident/6
68     (clsql:sql ["foo" bar])
69  "\"foo\".BAR")
70
71 (deftest :syntax/ident/7
72     (clsql:sql ["foo" bar :integer])
73  "\"foo\".BAR")
74
75
76 (deftest :syntax/attribute/1
77     (clsql:sql (clsql:sql-expression :table 'foo :attribute 'bar))
78   "FOO.BAR")
79
80 (deftest :syntax/attribute/2
81     (clsql:sql (clsql:sql-expression :table 'foo :attribute "bar"))
82   "FOO.\"bar\"")
83
84 (deftest :syntax/attribute/3
85     (clsql:sql (clsql:sql-expression :table "foo" :attribute 'bar))
86   "\"foo\".BAR")
87
88 (deftest :syntax/attribute/4
89     (clsql:sql (clsql:sql-expression :table "foo" :attribute "bar"))
90   "\"foo\".\"bar\"")
91
92
93 (deftest :syntax/subquery/1
94     (clsql:sql [any '(3 4)])
95  "ANY((3,4))")
96
97 (deftest :syntax/subquery/2
98     (clsql:sql [in [foo] '(foo bar baz)])
99   "(FOO IN (FOO,BAR,BAZ))")
100
101 (deftest :syntax/subquery/3
102     (clsql:sql [all '(foo bar baz)])
103   "ALL((FOO,BAR,BAZ))")
104
105 (deftest :syntax/subquery/4
106     (clsql:sql [exists '(foo bar baz)])
107   "EXISTS((FOO,BAR,BAZ))")
108
109 (deftest :syntax/subquery/5
110     (clsql:sql [some '(foo bar baz)])
111   "SOME((FOO,BAR,BAZ))")
112
113
114 (deftest :syntax/aggregate/1
115     (clsql:sql [max [+ [foo] [* 1000 [bar]]]])
116  "MAX((FOO + (1000 * BAR)))")
117
118 (deftest :syntax/aggregate/2
119     (clsql:sql [avg [+ [foo] [* 1000 [bar]]]])
120  "AVG((FOO + (1000 * BAR)))")
121
122 (deftest :syntax/aggregate/3
123     (clsql:sql [min [+ [foo] [* 1000 [bar]]]])
124  "MIN((FOO + (1000 * BAR)))")
125
126 (deftest :syntax/aggregate/4
127     (clsql:sql [sum [foo] [bar]])
128  "SUM(FOO,BAR)")
129
130 (deftest :syntax/aggregate/5
131     (clsql:sql [count [foo]])
132  "COUNT(FOO)")
133
134
135 (deftest :syntax/logical/1
136     (values (clsql:sql [and [foo] [bar]])
137             (clsql:sql [or [foo] [bar]]))
138   "(FOO AND BAR)"
139   "(FOO OR BAR)")
140
141 (deftest :syntax/logical/2
142     (clsql:sql [not [foo]])
143   "(NOT (FOO))")
144
145 ;;; Test how we apply logical operators when we have different numbers of children
146 ;;; This is useful if we wish to (apply #'sql-and some-list) without having to do
147 ;;; alot of length checking
148 (deftest :syntax/logical/3
149     (values (clsql:sql [and ])
150             (clsql:sql [and [foo]])
151             (clsql:sql [and [not [foo]]])
152             (clsql:sql [and [foo] [bar] [baz]]))
153   ""
154   "FOO"
155   "(NOT (FOO))"
156   "(FOO AND BAR AND BAZ)")
157
158 (deftest :syntax/logical/4
159     (clsql:sql [and [= [foo] [bar]]])
160   "(FOO = BAR)")
161
162 (deftest :syntax/logical/5
163   (clsql:sql [and [= [foo] [bar]]
164                   [= [bar] [bast]]
165                   [= [block] [blech]]])
166   "((FOO = BAR) AND (BAR = BAST) AND (BLOCK = BLECH))")
167
168 (deftest :syntax/logical/6
169     (clsql:sql
170      (apply #'sql-and
171             (list [= [foo] [bar]]
172                   [and ]
173                   [and [= [bar] [bast]]])))
174   "((FOO = BAR) AND (BAR = BAST))")
175
176
177 (deftest :syntax/null/1
178     (clsql:sql [null [foo]])
179   "(FOO IS NULL)")
180
181 (deftest :syntax/null/2
182     (clsql:sql [not [null [foo]]])
183   "(NOT ((FOO IS NULL)))")
184
185 (deftest :syntax/null/3
186     (clsql:sql [null])
187   "NULL")
188
189 (deftest :syntax/null/4
190     (clsql:sql [not [null]])
191   "(NOT (NULL))")
192
193
194
195 (deftest :syntax/relational/1
196     (clsql:sql [> [baz] [beep]])
197   "(BAZ > BEEP)")
198
199 (deftest :syntax/relational/2
200     (let ((x 10))
201       (clsql:sql [> [foo] x]))
202   "(FOO > 10)")
203
204 (deftest :syntax/relational/3
205     (clsql:sql [>= [baz] [beep]])
206   "(BAZ >= BEEP)")
207
208 (deftest :syntax/relational/4
209     (clsql:sql [< [baz] [beep]])
210   "(BAZ < BEEP)")
211
212 (deftest :syntax/relational/5
213     (clsql:sql [= [baz] [beep]])
214   "(BAZ = BEEP)")
215
216 (deftest :syntax/relational/6
217     (clsql:sql [<> [baz] [beep]])
218   "(BAZ <> BEEP)")
219
220
221 (deftest :syntax/between/1
222     (clsql:sql [between [- [foo] 1] [* [bar] 5] [/ [baz] 9]])
223   "(FOO - 1) BETWEEN (BAR * 5) AND (BAZ / 9)")
224
225 (deftest :syntax/between/2
226     (clsql:sql [not [between [- [foo] 1] [* [bar] 5] [/ [baz] 9]]])
227   "(NOT ((FOO - 1) BETWEEN (BAR * 5) AND (BAZ / 9)))")
228
229
230 (deftest :syntax/arithmetic/1
231     (clsql:sql [+ [foo bar] [baz]])
232  "(FOO.BAR + BAZ)")
233
234 (deftest :syntax/arithmetic/2
235     (clsql:sql [- [foo bar] [baz]])
236  "(FOO.BAR - BAZ)")
237
238 (deftest :syntax/arithmetic/3
239     (clsql:sql [/ [foo bar] [baz]])
240  "(FOO.BAR / BAZ)")
241
242 (deftest :syntax/arithmetic/4
243     (clsql:sql [* [foo bar] [baz]])
244  "(FOO.BAR * BAZ)")
245
246 (deftest :syntax/arithmetic/5
247     (clsql:sql [- [foo bar]])
248  "(- (FOO.BAR))")
249
250 (deftest :syntax/arithmetic/6
251     (clsql:sql [* 2 3])
252   "(2 * 3)")
253
254
255 (deftest :syntax/substr/1
256     (clsql:sql [substr [hello] 1 4])
257  "SUBSTR(HELLO,1,4)")
258
259 (deftest :syntax/substring/1
260     (clsql:sql [substring [hello] 1 4])
261  "SUBSTRING(HELLO,1,4)")
262
263
264 (deftest :syntax/concat/1
265     (clsql:sql [|| [foo] [bar] [baz]])
266  "(FOO || BAR || BAZ)")
267
268 (deftest :syntax/concat/2
269     (clsql:sql [concat [foo] [bar]])
270  "CONCAT(FOO,BAR)")
271
272
273 (deftest :syntax/pattern/1
274     (clsql:sql [like [foo] "%v"])
275   "(FOO LIKE '%v')")
276
277 (deftest :syntax/pattern/2
278     (clsql:sql [not [like [foo] "%v"]])
279   "(NOT ((FOO LIKE '%v')))")
280
281
282 (deftest :syntax/distinct/1
283     (clsql:sql [distinct [foo bar :string]])
284  "DISTINCT FOO.BAR")
285
286 (deftest :syntax/distinct/2
287     (clsql:sql [distinct [foo :string] [bar :integer]])
288  "DISTINCT FOO, BAR")
289
290
291 (deftest :syntax/order-by/1
292     (clsql:sql [order-by [foo]])
293  "ORDER BY FOO")
294
295 (deftest :syntax/group-by/1
296     (clsql:sql [group-by [foo]])
297  "GROUP BY FOO")
298
299 (deftest :syntax/group-by/2
300     (clsql:sql
301      (clsql-sys::make-query [foo] [bar] [count [foo]]
302       :from [table]
303       :group-by '([foo] [bar])
304       :order-by '([foo] [bar])))
305   "SELECT FOO,BAR,COUNT(FOO) FROM TABLE GROUP BY FOO,BAR ORDER BY FOO,BAR")
306
307
308 (deftest :syntax/coalesce/1
309     (clsql:sql [coalesce [foo] [bar] "not specified"])
310  "COALESCE(FOO,BAR,'not specified')")
311
312 (deftest :syntax/coalesce/2
313     (clsql:sql [nvl [foo] "not specified"])
314  "COALESCE(FOO,'not specified')")
315
316 (deftest :syntax/nvl/1
317     (clsql:sql [nvl [foo] "not specified"])
318  "COALESCE(FOO,'not specified')")
319
320
321
322 (deftest :syntax/sets/1
323     (clsql:sql [union [select [foo] :from [bar]] [select [baz] :from [bar]]])
324  "SELECT FOO FROM BAR UNION SELECT BAZ FROM BAR")
325
326 (deftest :syntax/sets/2
327     (clsql:sql [intersect [select [foo] :from [bar]] [select [baz] :from [bar]]])
328  "SELECT FOO FROM BAR INTERSECT SELECT BAZ FROM BAR")
329
330 (deftest :syntax/sets/3
331     (clsql:sql [except [select [foo] :from [bar]] [select [baz] :from [bar]]])
332  "SELECT FOO FROM BAR EXCEPT SELECT BAZ FROM BAR")
333
334 (deftest :syntax/sets/4
335     (clsql:sql [minus [select [foo] :from [bar]] [select [baz] :from [bar]]])
336  "SELECT FOO FROM BAR MINUS SELECT BAZ FROM BAR")
337
338
339 (deftest :syntax/function/1
340     (clsql:sql [function "COS" [age]])
341   "COS(AGE)")
342
343 (deftest :syntax/function/2
344     (clsql:sql [function "TO_DATE" "02/06/99" "mm/DD/RR"])
345   "TO_DATE('02/06/99','mm/DD/RR')")
346
347
348 (deftest :syntax/query/1
349     (clsql:sql [select [person_id] [surname] :from [person]])
350   "SELECT PERSON_ID,SURNAME FROM PERSON")
351
352 (deftest :syntax/query/2
353     (clsql:sql [select [foo] [bar *]
354                       :from '([baz] [bar])
355                       :where [or [= [foo] 3]
356                                  [> [baz.quux] 10]]])
357   "SELECT FOO,BAR.* FROM BAZ,BAR WHERE ((FOO = 3) OR (BAZ.QUUX > 10))")
358
359 (deftest :syntax/query/3
360     (clsql:sql [select [foo bar] [baz]
361                       :from '([foo] [quux])
362                       :where [or [> [baz] 3]
363                                  [like [foo bar] "SU%"]]])
364   "SELECT FOO.BAR,BAZ FROM FOO,QUUX WHERE ((BAZ > 3) OR (FOO.BAR LIKE 'SU%'))")
365
366 (deftest :syntax/query/4
367     (clsql:sql [select [count [*]] :from [emp]])
368   "SELECT COUNT(*) FROM EMP")
369
370
371 (deftest :syntax/expression/1
372     (clsql:sql
373      (clsql:sql-operation
374       'select
375       (clsql:sql-expression :table 'foo :attribute 'bar)
376       (clsql:sql-expression :attribute 'baz)
377       :from (list
378              (clsql:sql-expression :table 'foo)
379              (clsql:sql-expression :table 'quux))
380       :where
381       (clsql:sql-operation 'or
382                           (clsql:sql-operation
383                            '>
384                            (clsql:sql-expression :attribute 'baz)
385                            3)
386                           (clsql:sql-operation
387                            'like
388                            (clsql:sql-expression :table 'foo
389                                                 :attribute 'bar)
390                            "SU%"))))
391   "SELECT FOO.BAR,BAZ FROM FOO,QUUX WHERE ((BAZ > 3) OR (FOO.BAR LIKE 'SU%'))")
392
393 (deftest :syntax/expression/2
394     (clsql:sql
395      (apply (clsql:sql-operator 'and)
396             (loop for table in '(thistime nexttime sometime never)
397                   for count from 42
398                   collect
399                   [function "BETWEEN"
400                             (clsql:sql-expression :table table
401                                                  :attribute 'bar)
402                             (clsql:sql-operation '* [hip] [hop])
403                             count]
404                   collect
405                   [like (clsql:sql-expression :table table
406                                              :attribute 'baz)
407                         (clsql:sql table)])))
408   "(BETWEEN(THISTIME.BAR,(HIP * HOP),42) AND (THISTIME.BAZ LIKE 'THISTIME') AND BETWEEN(NEXTTIME.BAR,(HIP * HOP),43) AND (NEXTTIME.BAZ LIKE 'NEXTTIME') AND BETWEEN(SOMETIME.BAR,(HIP * HOP),44) AND (SOMETIME.BAZ LIKE 'SOMETIME') AND BETWEEN(NEVER.BAR,(HIP * HOP),45) AND (NEVER.BAZ LIKE 'NEVER'))")
409
410 ))
411
412 #.(clsql:restore-sql-reader-syntax-state)