;;;; -*- Mode: LISP; Syntax: ANSI-Common-Lisp; Base: 10 -*-
-;;;; ======================================================================
-;;;; File: table.lisp
-;;;; Updated: <04/04/2004 12:05:03 marcusp>
-;;;; ======================================================================
+;;;; *************************************************************************
;;;;
-;;;; Description ==========================================================
-;;;; ======================================================================
+;;;; $Id$
;;;;
;;;; The CLSQL Functional Data Definition Language (FDDL)
;;;; including functions for schema manipulation. Currently supported
;;;; SQL objects include tables, views, indexes, attributes and
;;;; sequences.
;;;;
-;;;; ======================================================================
+;;;; This file is part of CLSQL.
+;;;;
+;;;; CLSQL users are granted the rights to distribute and use this software
+;;;; as governed by the terms of the Lisp Lesser GNU Public License
+;;;; (http://opensource.franz.com/preamble.html), also known as the LLGPL.
+;;;; *************************************************************************
(in-package #:clsql-sys)
;; Utilities
-(defun database-identifier (name)
+(defun database-identifier (name database)
(sql-escape (etypecase name
(string
- (string-upcase name))
+ (convert-to-db-default-case name database))
(sql-ident
- (sql-output name))
+ (sql-output name database))
(symbol
- (sql-output name)))))
+ (sql-output name database)))))
;; Tables
-(defvar *table-schemas* (make-hash-table :test #'equal)
- "Hash of schema name to table lists.")
-
(defun create-table (name description &key (database *default-database*)
- (constraints nil))
+ (constraints nil) (transactions t))
"Create a table called NAME, in DATABASE which defaults to
*DEFAULT-DATABASE*, containing the attributes in DESCRIPTION which is
a list containing lists of attribute-name and type information pairs."
(stmt (make-instance 'sql-create-table
:name table-name
:columns description
- :modifiers constraints)))
- (pushnew table-name (gethash *default-schema* *table-schemas*)
- :test #'equal)
+ :modifiers constraints
+ :transactions transactions)))
(execute-command stmt :database database)))
(defun drop-table (name &key (if-does-not-exist :error)
*DEFAULT-DATABASE*. If the table does not exist and IF-DOES-NOT-EXIST
is :ignore then DROP-TABLE returns nil whereas an error is signalled
if IF-DOES-NOT-EXIST is :error."
- (let ((table-name (database-identifier name)))
+ (let ((table-name (database-identifier name database)))
(ecase if-does-not-exist
(:ignore
(unless (table-exists-p table-name :database database)
tables are considered. If OWNER is a string, this denotes a username
and only tables owned by OWNER are considered. Table names are
returned as a list of strings."
- (when (member (database-identifier name)
+ (when (member (database-identifier name database)
(list-tables :owner owner :database database)
:test #'string-equal)
t))
;; Views
-(defvar *view-schemas* (make-hash-table :test #'equal)
- "Hash of schema name to view lists.")
-
(defun create-view (name &key as column-list (with-check-option nil)
(database *default-database*))
"Creates a view called NAME using the AS query and the optional
:column-list column-list
:query as
:with-check-option with-check-option)))
- (pushnew view-name (gethash *default-schema* *view-schemas*) :test #'equal)
(execute-command stmt :database database)))
(defun drop-view (name &key (if-does-not-exist :error)
*DEFAULT-DATABASE*. If the view does not exist and IF-DOES-NOT-EXIST
is :ignore then DROP-VIEW returns nil whereas an error is signalled if
IF-DOES-NOT-EXIST is :error."
- (let ((view-name (database-identifier name)))
+ (let ((view-name (database-identifier name database)))
(ecase if-does-not-exist
(:ignore
(unless (view-exists-p view-name :database database)
considered. If OWNER is a string, this denotes a username and only
views owned by OWNER are considered. View names are returned as a list
of strings."
- (when (member (database-identifier name)
+ (when (member (database-identifier name database)
(list-views :owner owner :database database)
:test #'string-equal)
t))
;; Indexes
-(defvar *index-schemas* (make-hash-table :test #'equal)
- "Hash of schema name to index lists.")
-
(defun create-index (name &key on (unique nil) attributes
(database *default-database*))
"Creates an index called NAME on the table specified by ON. The
UNIQUE to T includes UNIQUE in the SQL index command, specifying that
the columns indexed must contain unique values. The default value of
UNIQUE is nil. The default value of DATABASE is *DEFAULT-DATABASE*."
- (let* ((index-name (database-identifier name))
- (table-name (database-identifier on))
- (attributes (mapcar #'database-identifier (listify attributes)))
+ (let* ((index-name (database-identifier name database))
+ (table-name (database-identifier on database))
+ (attributes (mapcar #'(lambda (a) (database-identifier a database)) (listify attributes)))
(stmt (format nil "CREATE ~A INDEX ~A ON ~A (~{~A~^, ~})"
(if unique "UNIQUE" "")
index-name table-name attributes)))
- (pushnew index-name (gethash *default-schema* *index-schemas*))
(execute-command stmt :database database)))
(defun drop-index (name &key (if-does-not-exist :error)
is :ignore then DROP-INDEX returns nil whereas an error is signalled
if IF-DOES-NOT-EXIST is :error. The argument ON allows the optional
specification of a table to drop the index from."
- (let ((index-name (database-identifier name)))
+ (let ((index-name (database-identifier name database)))
(ecase if-does-not-exist
(:ignore
(unless (index-exists-p index-name :database database)
(return-from drop-index)))
(:error t))
+ (unless (db-type-use-column-on-drop-index?
+ (database-underlying-type database))
+ (setq on nil))
(execute-command (format nil "DROP INDEX ~A~A" index-name
(if (null on) ""
(concatenate 'string " ON "
- (database-identifier on))))
+ (database-identifier on database))))
:database database)))
(defun list-indexes (&key (owner nil) (database *default-database*))
OWNER is a string, this denotes a username and only indexs owned by
OWNER are considered. Index names are returned as a list of strings."
(database-list-indexes database :owner owner))
+
+(defun list-table-indexes (table &key (owner nil)
+ (database *default-database*))
+ "List all indexes in DATABASE for a TABLE, which defaults to
+*default-database*. If OWNER is :all , all indexs are considered. If
+OWNER is a string, this denotes a username and only indexs owned by
+OWNER are considered. Index names are returned as a list of strings."
+ (database-list-table-indexes (database-identifier table database)
+ database :owner owner))
(defun index-exists-p (name &key (owner nil) (database *default-database*))
"Test for existence of an index called NAME in DATABASE which
considered. If OWNER is a string, this denotes a username and only
indexs owned by OWNER are considered. Index names are returned as a
list of strings."
- (when (member (database-identifier name)
+ (when (member (database-identifier name database)
(list-indexes :owner owner :database database)
:test #'string-equal)
t))
username and only attributes owned by OWNER are considered. Attribute
names are returned as a list of strings. Attributes are returned as a
list of strings."
- (database-list-attributes (database-identifier name) database :owner owner))
+ (database-list-attributes (database-identifier name database) database :owner owner))
(defun attribute-type (attribute table &key (owner nil)
(database *default-database*))
considered. If OWNER is a string, this denotes a username and only
attributes owned by OWNER are considered. Attribute names are returned
as a list of strings. Attributes are returned as a list of strings."
- (database-attribute-type (database-identifier attribute)
- (database-identifier table)
+ (database-attribute-type (database-identifier attribute database)
+ (database-identifier table database)
database
:owner owner))
;; Sequences
-(defvar *sequence-schemas* (make-hash-table :test #'equal)
- "Hash of schema name to sequence lists.")
-
(defun create-sequence (name &key (database *default-database*))
"Create a sequence called NAME in DATABASE which defaults to
*DEFAULT-DATABASE*."
- (let ((sequence-name (database-identifier name)))
- (database-create-sequence sequence-name database)
- (pushnew sequence-name (gethash *default-schema* *sequence-schemas*)
- :test #'equal))
+ (let ((sequence-name (database-identifier name database)))
+ (database-create-sequence sequence-name database))
(values))
(defun drop-sequence (name &key (if-does-not-exist :error)
*DEFAULT-DATABASE*. If the sequence does not exist and
IF-DOES-NOT-EXIST is :ignore then DROP-SEQUENCE returns nil whereas an
error is signalled if IF-DOES-NOT-EXIST is :error."
- (let ((sequence-name (database-identifier name)))
+ (let ((sequence-name (database-identifier name database)))
(ecase if-does-not-exist
(:ignore
(unless (sequence-exists-p sequence-name :database database)
(database *default-database*))
"Test for existence of a sequence called NAME in DATABASE which
defaults to *DEFAULT-DATABASE*."
- (when (member (database-identifier name)
+ (when (member (database-identifier name database)
(list-sequences :owner owner :database database)
:test #'string-equal)
t))
(defun sequence-next (name &key (database *default-database*))
"Return the next value in the sequence NAME in DATABASE."
- (database-sequence-next (database-identifier name) database))
+ (database-sequence-next (database-identifier name database) database))
(defun set-sequence-position (name position &key (database *default-database*))
"Explicitly set the the position of the sequence NAME in DATABASE to
POSITION."
- (database-set-sequence-position (database-identifier name) position database))
+ (database-set-sequence-position (database-identifier name database) position database))
(defun sequence-last (name &key (database *default-database*))
"Return the last value of the sequence NAME in DATABASE."
- (database-sequence-last (database-identifier name) database))
+ (database-sequence-last (database-identifier name database) database))