r9234: rename package
[clsql.git] / sql / table.lisp
1 ;;;; -*- Mode: LISP; Syntax: ANSI-Common-Lisp; Base: 10 -*-
2 ;;;; *************************************************************************
3 ;;;;
4 ;;;; $Id$
5 ;;;;
6 ;;;; The CLSQL Functional Data Definition Language (FDDL)
7 ;;;; including functions for schema manipulation. Currently supported
8 ;;;; SQL objects include tables, views, indexes, attributes and
9 ;;;; sequences.
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)
19
20
21 ;; Utilities
22
23 (defun database-identifier (name database)
24   (sql-escape (etypecase name
25                 (string
26                  (convert-to-db-default-case name database))
27                 (sql-ident
28                  (sql-output name database))
29                 (symbol
30                  (sql-output name database)))))
31
32
33 ;; Tables 
34
35 (defun create-table (name description &key (database *default-database*)
36                           (constraints nil) (transactions t))
37   "Create a table called NAME, in DATABASE which defaults to
38 *DEFAULT-DATABASE*, containing the attributes in DESCRIPTION which is
39 a list containing lists of attribute-name and type information pairs."
40   (let* ((table-name (etypecase name 
41                        (symbol (sql-expression :attribute name))
42                        (string (sql-expression :attribute (make-symbol name)))
43                        (sql-ident name)))
44          (stmt (make-instance 'sql-create-table
45                               :name table-name
46                               :columns description
47                               :modifiers constraints
48                               :transactions transactions)))
49     (execute-command stmt :database database)))
50
51 (defun drop-table (name &key (if-does-not-exist :error)
52                         (database *default-database*))
53   "Drops table NAME from DATABASE which defaults to
54 *DEFAULT-DATABASE*. If the table does not exist and IF-DOES-NOT-EXIST
55 is :ignore then DROP-TABLE returns nil whereas an error is signalled
56 if IF-DOES-NOT-EXIST is :error."
57   (let ((table-name (database-identifier name database)))
58     (ecase if-does-not-exist
59       (:ignore
60        (unless (table-exists-p table-name :database database)
61          (return-from drop-table nil)))
62       (:error
63        t))
64     (let ((expr (concatenate 'string "DROP TABLE " table-name)))
65       (execute-command expr :database database))))
66
67 (defun list-tables (&key (owner nil) (database *default-database*))
68   "List all tables in DATABASE which defaults to
69 *DEFAULT-DATABASE*. If OWNER is nil, only user-owned tables are
70 considered. This is the default. If OWNER is :all , all tables are
71 considered. If OWNER is a string, this denotes a username and only
72 tables owned by OWNER are considered. Table names are returned as a
73 list of strings."
74   (database-list-tables database :owner owner))
75
76 (defun table-exists-p (name &key (owner nil) (database *default-database*))
77   "Test for existence of an SQL table called NAME in DATABASE which
78 defaults to *DEFAULT-DATABASE*. If OWNER is nil, only user-owned
79 tables are considered. This is the default. If OWNER is :all , all
80 tables are considered. If OWNER is a string, this denotes a username
81 and only tables owned by OWNER are considered. Table names are
82 returned as a list of strings."
83   (when (member (database-identifier name database)
84                 (list-tables :owner owner :database database)
85                 :test #'string-equal)
86     t))
87
88
89 ;; Views 
90
91 (defun create-view (name &key as column-list (with-check-option nil)
92                          (database *default-database*))
93   "Creates a view called NAME using the AS query and the optional
94 COLUMN-LIST and WITH-CHECK-OPTION. The COLUMN-LIST argument is a list
95 of columns to add to the view. The WITH-CHECK-OPTION adds 'WITH CHECK
96 OPTION' to the resulting SQL. The default value of WITH-CHECK-OPTION
97 is NIL. The default value of DATABASE is *DEFAULT-DATABASE*."
98   (let* ((view-name (etypecase name 
99                       (symbol (sql-expression :attribute name))
100                       (string (sql-expression :attribute (make-symbol name)))
101                       (sql-ident name)))
102          (stmt (make-instance 'sql-create-view
103                               :name view-name
104                               :column-list column-list
105                               :query as
106                               :with-check-option with-check-option)))
107     (execute-command stmt :database database)))
108
109 (defun drop-view (name &key (if-does-not-exist :error)
110                        (database *default-database*))
111   "Deletes view NAME from DATABASE which defaults to
112 *DEFAULT-DATABASE*. If the view does not exist and IF-DOES-NOT-EXIST
113 is :ignore then DROP-VIEW returns nil whereas an error is signalled if
114 IF-DOES-NOT-EXIST is :error."
115   (let ((view-name (database-identifier name database)))
116     (ecase if-does-not-exist
117       (:ignore
118        (unless (view-exists-p view-name :database database)
119          (return-from drop-view)))
120       (:error
121        t))
122     (let ((expr (concatenate 'string "DROP VIEW " view-name)))
123       (execute-command expr :database database))))
124
125 (defun list-views (&key (owner nil) (database *default-database*))
126   "List all views in DATABASE which defaults to *DEFAULT-DATABASE*. If
127 OWNER is nil, only user-owned views are considered. This is the
128 default. If OWNER is :all , all views are considered. If OWNER is a
129 string, this denotes a username and only views owned by OWNER are
130 considered. View names are returned as a list of strings."
131   (database-list-views database :owner owner))
132
133 (defun view-exists-p (name &key (owner nil) (database *default-database*))
134   "Test for existence of an SQL view called NAME in DATABASE which
135 defaults to *DEFAULT-DATABASE*. If OWNER is nil, only user-owned views
136 are considered. This is the default. If OWNER is :all , all views are
137 considered. If OWNER is a string, this denotes a username and only
138 views owned by OWNER are considered. View names are returned as a list
139 of strings."
140   (when (member (database-identifier name database)
141                 (list-views :owner owner :database database)
142                 :test #'string-equal)
143     t))
144
145
146 ;; Indexes 
147
148 (defun create-index (name &key on (unique nil) attributes
149                           (database *default-database*))
150   "Creates an index called NAME on the table specified by ON. The
151 attributes of the table to index are given by ATTRIBUTES. Setting
152 UNIQUE to T includes UNIQUE in the SQL index command, specifying that
153 the columns indexed must contain unique values. The default value of
154 UNIQUE is nil. The default value of DATABASE is *DEFAULT-DATABASE*."
155   (let* ((index-name (database-identifier name database))
156          (table-name (database-identifier on database))
157          (attributes (mapcar #'(lambda (a) (database-identifier a database)) (listify attributes)))
158          (stmt (format nil "CREATE ~A INDEX ~A ON ~A (~{~A~^, ~})"
159                        (if unique "UNIQUE" "")
160                        index-name table-name attributes)))
161     (execute-command stmt :database database)))
162
163 (defun drop-index (name &key (if-does-not-exist :error)
164                         (on nil)
165                         (database *default-database*))
166   "Deletes index NAME from table FROM in DATABASE which defaults to
167 *DEFAULT-DATABASE*. If the index does not exist and IF-DOES-NOT-EXIST
168 is :ignore then DROP-INDEX returns nil whereas an error is signalled
169 if IF-DOES-NOT-EXIST is :error. The argument ON allows the optional
170 specification of a table to drop the index from."
171   (let ((index-name (database-identifier name database)))
172     (ecase if-does-not-exist
173       (:ignore
174        (unless (index-exists-p index-name :database database)
175          (return-from drop-index)))
176       (:error t))
177     (unless (db-type-use-column-on-drop-index? 
178              (database-underlying-type database))
179       (setq on nil))
180     (execute-command (format nil "DROP INDEX ~A~A" index-name
181                              (if (null on) ""
182                                  (concatenate 'string " ON "
183                                               (database-identifier on database))))
184                      :database database)))
185
186 (defun list-indexes (&key (owner nil) (database *default-database*))
187   "List all indexes in DATABASE, which defaults to
188 *default-database*. If OWNER is :all , all indexs are considered. If
189 OWNER is a string, this denotes a username and only indexs owned by
190 OWNER are considered. Index names are returned as a list of strings."
191   (database-list-indexes database :owner owner))
192
193 (defun list-table-indexes (table &key (owner nil)
194                                       (database *default-database*))
195   "List all indexes in DATABASE for a TABLE, which defaults to
196 *default-database*. If OWNER is :all , all indexs are considered. If
197 OWNER is a string, this denotes a username and only indexs owned by
198 OWNER are considered. Index names are returned as a list of strings."
199   (database-list-table-indexes (database-identifier table database)
200                                database :owner owner))
201   
202 (defun index-exists-p (name &key (owner nil) (database *default-database*))
203   "Test for existence of an index called NAME in DATABASE which
204 defaults to *DEFAULT-DATABASE*. If OWNER is :all , all indexs are
205 considered. If OWNER is a string, this denotes a username and only
206 indexs owned by OWNER are considered. Index names are returned as a
207 list of strings."
208   (when (member (database-identifier name database)
209                 (list-indexes :owner owner :database database)
210                 :test #'string-equal)
211     t))
212
213 ;; Attributes 
214
215 (defvar *cache-table-queries-default* "Default atribute type caching behavior.")
216
217 (defun cache-table-queries (table &key (action nil) (database *default-database*))
218   "Provides per-table control on the caching in a particular database
219 connection of attribute type information using during update
220 operations. If TABLE is a string, it is the name of the table for
221 which caching is to be altered. If TABLE is t, then the action applies
222 to all tables. If TABLE is :default, then the default caching action
223 is set for those tables which do not have an explicit setting. ACTION
224 specifies the caching action. The value t means cache the attribute
225 type information. The value nil means do not cache the attribute type
226 information. If TABLE is :default, the setting applies to all tables
227 which do not have an explicit setup. The value :flush means remove any
228 existing cache for table in database, but continue to cache. This
229 function should be called with action :flush when the attribute
230 specifications in table have changed."
231   (with-slots (attribute-cache) database
232     (cond
233       ((stringp table)
234        (multiple-value-bind (val found) (gethash table attribute-cache)
235          (cond
236            ((and found (eq action :flush))
237             (setf (gethash table attribute-cache) (list t nil)))
238            ((and found (eq action t))
239             (setf (gethash table attribute-cache) (list t (second val))))
240            ((and found (null action))
241             (setf (gethash table attribute-cache) (list nil nil)))
242            ((not found)
243             (setf (gethash table attribute-cache) (list action nil))))))
244       ((eq table t)
245        (maphash (lambda (k v)
246                   (cond
247                     ((eq action :flush)
248                      (setf (gethash k attribute-cache) (list t nil)))
249                     ((null action)
250                      (setf (gethash k attribute-cache) (list nil nil)))
251                     ((eq t action)
252                      (setf (gethash k attribute-cache) (list t (second v))))))
253                 attribute-cache))
254       ((eq table :default)
255        (maphash (lambda (k v)
256                   (when (eq (first v) :unspecified)
257                     (cond
258                       ((eq action :flush)
259                        (setf (gethash k attribute-cache) (list t nil)))
260                       ((null action)
261                        (setf (gethash k attribute-cache) (list nil nil)))
262                       ((eq t action)
263                        (setf (gethash k attribute-cache) (list t (second v)))))))
264                 attribute-cache))))
265   (values))
266                   
267
268 (defun list-attributes (name &key (owner nil) (database *default-database*))
269   "List the attributes of a attribute called NAME in DATABASE which
270 defaults to *DEFAULT-DATABASE*. If OWNER is nil, only user-owned
271 attributes are considered. This is the default. If OWNER is :all , all
272 attributes are considered. If OWNER is a string, this denotes a
273 username and only attributes owned by OWNER are considered. Attribute
274 names are returned as a list of strings. Attributes are returned as a
275 list of strings."
276   (database-list-attributes (database-identifier name database) database :owner owner))
277
278 (defun attribute-type (attribute table &key (owner nil)
279                                  (database *default-database*))
280   "Return the field type of the ATTRIBUTE in TABLE.  The optional
281 keyword argument DATABASE specifies the database to query, defaulting
282 to *DEFAULT-DATABASE*. If OWNER is nil, only user-owned attributes are
283 considered. This is the default. If OWNER is :all , all attributes are
284 considered. If OWNER is a string, this denotes a username and only
285 attributes owned by OWNER are considered. Attribute names are returned
286 as a list of strings. Attributes are returned as a list of strings."
287   (database-attribute-type (database-identifier attribute database)
288                            (database-identifier table database)
289                            database
290                            :owner owner))
291
292 (defun list-attribute-types (table &key (owner nil)
293                                    (database *default-database*))
294   "Returns type information for the attributes in TABLE from DATABASE
295 which has a default value of *default-database*. If OWNER is nil, only
296 user-owned attributes are considered. This is the default. If OWNER is
297 :all, all attributes are considered. If OWNER is a string, this
298 denotes a username and only attributes owned by OWNER are
299 considered. Returns a list in which each element is a list (attribute
300 datatype). Attribute is a string denoting the atribute name. Datatype
301 is the vendor-specific type returned by ATTRIBUTE-TYPE."
302   (with-slots (attribute-cache) database
303     (let ((table-ident (database-identifier table database)))
304       (multiple-value-bind (val found) (gethash table-ident attribute-cache)
305         (if (and found (second val))
306             (second val)
307             (let ((types (mapcar #'(lambda (attribute)
308                                      (cons attribute
309                                            (multiple-value-list
310                                             (database-attribute-type
311                                              (database-identifier attribute database)
312                                              table-ident
313                                              database
314                                              :owner owner))))
315                                  (list-attributes table :database database :owner owner))))
316               (cond
317                 ((and (not found) (eq t *cache-table-queries-default*))
318                  (setf (gethash table-ident attribute-cache) (list :unspecified types)))
319                 ((and found (eq t (first val)) 
320                       (setf (gethash table-ident attribute-cache) (list t types)))))
321               types))))))
322   
323
324 ;; Sequences 
325
326 (defun create-sequence (name &key (database *default-database*))
327   "Create a sequence called NAME in DATABASE which defaults to
328 *DEFAULT-DATABASE*."
329   (let ((sequence-name (database-identifier name database)))
330     (database-create-sequence sequence-name database))
331   (values))
332
333 (defun drop-sequence (name &key (if-does-not-exist :error)
334                            (database *default-database*))
335   "Drops sequence NAME from DATABASE which defaults to
336 *DEFAULT-DATABASE*. If the sequence does not exist and
337 IF-DOES-NOT-EXIST is :ignore then DROP-SEQUENCE returns nil whereas an
338 error is signalled if IF-DOES-NOT-EXIST is :error."
339   (let ((sequence-name (database-identifier name database)))
340     (ecase if-does-not-exist
341       (:ignore
342        (unless (sequence-exists-p sequence-name :database database)
343          (return-from drop-sequence)))
344       (:error t))
345     (database-drop-sequence sequence-name database))
346   (values))
347
348 (defun list-sequences (&key (owner nil) (database *default-database*))
349   "List all sequences in DATABASE, which defaults to
350 *default-database*. If OWNER is nil, only user-owned sequences are
351 considered. This is the default. If OWNER is :all , all sequences are
352 considered. If OWNER is a string, this denotes a username and only
353 sequences owned by OWNER are considered. Sequence names are returned
354 as a list of strings."
355   (database-list-sequences database :owner owner))
356
357 (defun sequence-exists-p (name &key (owner nil)
358                                (database *default-database*))
359   "Test for existence of a sequence called NAME in DATABASE which
360 defaults to *DEFAULT-DATABASE*."
361   (when (member (database-identifier name database)
362                 (list-sequences :owner owner :database database)
363                 :test #'string-equal)
364     t))
365   
366 (defun sequence-next (name &key (database *default-database*))
367   "Return the next value in the sequence NAME in DATABASE."
368   (database-sequence-next (database-identifier name database) database))
369
370 (defun set-sequence-position (name position &key (database *default-database*))
371   "Explicitly set the the position of the sequence NAME in DATABASE to
372 POSITION."
373   (database-set-sequence-position (database-identifier name database) position database))
374
375 (defun sequence-last (name &key (database *default-database*))
376   "Return the last value of the sequence NAME in DATABASE."
377   (database-sequence-last (database-identifier name database) database))
378
379 ;;; Remote Joins
380
381 (defvar *default-update-objects-max-len* nil
382   "The default maximum number of objects supplying data for a query when updating remote joins.")
383